c++c++17std-variant

Cleaner way to specify type to get from a std::variant?


I've got code that can be simplified to

std::variant<float, int> v[2] = foo();
int a = std::get<decltype(a)>(v[0]);
float b = std::get<decltype(b)>(v[1]);

Obviously this can go throw if foo() returns the wrong variants, but that's not my problem here. (The real code has a catch). My problem is that the decltype(a) violates the Don't Repeat Yourself principle.

Is there a cleaner way to initialize a and b, and still throw if the types do not match expectations? In particular, I don't want a static_cast<int>(std::get<float>(v)) if the variant contains a float while I'm trying to initialize an int.


Solution

  • You could wrap your call to get in a template that implicitly converts to the target type.

    template<typename... Ts>
    struct variant_unwrapper {
        std::variant<Ts...> & var;
        template <typename T>
        operator T() { return std::get<T>(var); }
    };
    
    template<typename... Ts>
    variant_unwrapper(std::variant<Ts...> &) -> variant_unwrapper<Ts...>;
    

    If you are targeting C++20, you don't need the deduction guide

    See it on coliru