I've migrated from boost::variant to std::variant, and hit a snag.
I was using a nice function in boost 'type()' that lets you get the currently held typeid. See https://www.boost.org/doc/libs/1_48_0/doc/html/boost/variant.html#id1752388-bb
How can this be achieved with std::variant?
I have an unordered map key'd on 'type_index', which holds some value 'std::function'. My variant, depending on the type, will determine what function I grab from the map to do some operation. (The code I have is far too large to post).
Any implementation ideas aside from writing a specific visitor for a particular std::variant? Maybe using the 'index()' function on the std::variant, to then index into the type list of the variant? Somewhat like this: How to get N-th type from a tuple?
template<class V>
std::type_info const& var_type(V const& v){
return std::visit( [](auto&&x)->decltype(auto){ return typeid(x); }, v );
}
Alternatively
template<class...Ts>
std::type_info const& var_type(std::variant<Ts...> const& v, std::optional<std::size_t> idx={}){
if (!idx) idx=v.index();
if(*idx==std::variant_npos) return typeid(void);
const std::array<std::type_info const*, sizeof...(Ts)> infos[]={ &typeid(Ts)... };
return *(infos[*idx]);
}
Which lets you ask about other indexes that are not active.
The problem is that the currently-selected type is known only at runtime, whereas "obtaining" a type must be done at compile-time. This is exactly why we have visitors — to hide away the unavoidable chain of if
statements behind the variant
implementation.
Instead of re-inventing that implementation, it would be best to perform your map dispatching from inside such a visitor.
Failing that, you will have to write your own chain of if
statements, producing code that's similar to the use of a visitor, but probably slower and less maintainable!
It is true that you can't implement such a thing by reading index()
then asking the variant to give you equivalent typeid
, as you could with the Boost implementation. But I'm pretty sure that's deliberate, because (as I've suggested above) any code making use of that would be ill-advised. Of course, if you really wanted to, you could write a visitor to produce such a typeid
! But then you still have to write conditional logic to deal with that value, when you could have just put the logic into the visitor in the first place.
来源:https://stackoverflow.com/questions/53696720/get-currently-held-typeid-of-stdvariant-like-boostvariant-type