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

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

我已经从 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'。根据类型的不同,我的变体将决定我从地图中获取什么功能来执行某些操作。 (我的代码太大 post)。

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

问题是当前选择的类型仅在运行时已知,而 "obtaining" 类型必须在编译时完成。这正是我们有访客的原因——隐藏 variant 实现背后不可避免的 if 语句链。

与其重新发明该实现,不如从此类访问者内部执行地图调度。

如果做不到这一点,您将不得不编写自己的 if 语句链,生成类似于访问者使用的代码,但可能更慢且更难维护!

的确,您无法通过阅读 index() 然后要求变体为您提供等效的 typeid 来实现这样的事情,就像您可以使用 Boost 实现一样。但我很确定这是故意的,因为(正如我上面所建议的)任何使用它的代码都是不明智的。当然,如果你真的想,你可以写一个访问者来制作这样的typeid!但是您仍然必须编写条件逻辑来处理该值,而您本来可以首先将逻辑放入访问者中。

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

这让您可以询问其他不活跃的索引。