简体   繁体   中英

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 .

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); }
};

See it on coliru

IMO it would be nice to allow template deduction to take over, so providing a helper function should do the job:

template<typename T, typename...VariantParams>
void get_from(const std::variant<VariantParams...>& v, T& value)
{
    value = ::std::get<T>(v);
}

int a;

get_from(v[0], a);

As @paulo says in the comments , seems like the DRY solution is to use auto for the declaration, changing:

int a = std::get<decltype(a)>(v[0]);

to:

auto a = std::get<int>(v[0]);

You only name the type ( int ) and the variable ( a ) once each. Doesn't work if you separate declaration and initialization, so you'd still need:

int a;
...
a = std::get<decltype(a)>(v[0]);

in that case, but if you write all your C++ code deferring declarations until the point of definition, it's not needed often.

Perhaps an additional layer of abstraction is the way to go:

struct bar 
{
    using type_of_a = int;
    std::variant <float, int> v = foo ();
    type_of_a a = std::get <type_of_a> (v);
};

Can't say I like it much though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM