Search code examples
c++variantvisitor-patternunreachable-code

How to visit on multiple variants with restricted to same type


I have a question about using a generic visitor with exclusion of non-equal types. Suppose I have the following:

using StorageT = std::variant<std::vector<int>, std::vector<double>>;

StorageT process_data(const StorageT &lhs, const StorageT &rhs) {
    return std::visit([&](auto &&l, auto &&r){
        return kernel(l, r);   // some templated kernel 
    },
    lhs, rhs);
}

Externally, I verify that the underlying stored type for variants lhs and rhs match. I'd like to write a generic visitor, without code being generated for all combinations of lhs and rhs where the underlying variant types are not the same.

As it stands, all combinations of the two underlying variant types are generated. Inside the lambda, I could write

if constexpr(std::is_same_v<Tl, TR>) {
    return kernel( ... );
} else {
    // Do nothing
    // static_assert(false);
    // Throw exception
}

Since all combinations of lhs and rhs are generated, the above code either a) complains about no return on the mismatch of types, b) fails due to the static assert, or c) generated a code path for an exception which will never be thrown (due to an external check of the types).

What is the best way to avoid code generation for all cases where the underlying types for lhs does not equal rhs?


Solution

  • Just visit one of the types and use that to determine the other type:

    StorageT process_data(const StorageT &lhs, const StorageT &rhs) {
        return std::visit([&](auto &&l){
            auto &r = std::get<std::remove_cvref_t<decltype(l)>>(rhs);
            return kernel(l, r); 
        },
        lhs);
    }