获取当前持有的std :: variant的typeid(例如boost :: variant type())

时间:2018-12-09 21:11:56

标签: c++ boost typeid std-variant

我已经从boost :: variant迁移到std :: variant,并遇到了障碍。

我在boost'type()'中使用了一个不错的函数,该函数可以让您获取当前持有的typeid。参见https://www.boost.org/doc/libs/1_48_0/doc/html/boost/variant.html#id1752388-bb

如何使用std :: variant实现此目标?

我在'type_index'上有一个无序的映射键,其中包含一些值'std :: function'。根据类型的不同,我的变体将确定我从地图上获取的功能以进行某些操作。 (我的代码太大了,无法发布)。

除了为特定的std :: variant编写特定的访问者之外,还有其他实现思路吗?也许在std :: variant上使用'index()'函数,然后索引到变量的类型列表中?有点像这样:How to get N-th type from a tuple?

2 个答案:

答案 0 :(得分:4)

问题在于当前选择的类型仅在运行时才知道,而“获取”类型则必须在编译时完成。这就是我们有访问者的原因-隐藏if实现背后不可避免的variant语句链。

最好不要在这样的访问者内部执行地图调度,而要重新发明该实现。

否则,您将不得不编写自己的if语句链,生成的代码与访问者的用法类似,但可能更慢且更难以维护!

确实,您无法通过阅读index()来实现这样的事情,然后要求变体为您提供等效的typeid,就像使用Boost实现一样。但是我敢肯定这是故意的,因为(如我在上面所建议的那样)任何利用它的代码都是不明智的。当然,如果您确实愿意,可以写一个访问者来产生这样一个typeid!但是当您只需要将逻辑放在访问者中时,仍然必须编写条件逻辑来处理该值。

答案 1 :(得分:3)

template<class V>
std::type_info const& var_type(V const& v){
  return std::visit( [](auto&&x)->decltype(auto){ return typeid(x); }, v );
}

或者

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

哪个让您询问其他不活跃的索引。