get currently held typeid of std::variant (like boost::variant type())

南笙酒味 提交于 2019-12-08 02:01:36

问题


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?


回答1:


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.




回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!