我有一个
std::variant
可能重复的类型,我想增加变体的活动索引。
这是一个演示我想做的事情的示例:
template <typename... Ts>
bool update_variant(std::variant<Ts>& v, std::tuple<work_generator<Ts>>& gen) {
return visit_with_index([&]<size_t Index /* the active index */>(auto& e) {
if (e.done()) {
// we are done with e
constexpr size_t next_index = Index + 1;
if constexpr (next_index == sizeof...(Ts)) {
// no more other work to do
return false;
} else {
// still have other work to do so we move on to the next variant alternative
v.emplace(
std::in_place_index_t<next_index>{},
std::get<next_index>(gen).create_worker()
);
return true;
}
} else {
// do some work on e, so e gets closer to the done state
e.do_some_work();
return true;
}
}, v);
}
为了实现这一点,我似乎需要类似于上面
visit_with_index
的东西,它为我提供当前索引作为编译时值。
除了上面编写我自己的
visit_with_index
版本(实际上是编写我自己的 std::visit
版本)之外,还有其他更简单的方法可以实现我想要的功能,而无需通过索引执行多次查找吗?
我会在索引上使用
visit
“直接”。
第一
template <typename... Ts>
auto get_index_variant(const std::variant<Ts...>& v)
{
return [&]<std::size_t...Is>(std::index_sequence<Is...>){
using Ret = std::variant<std::integral_constant<std::size_t, Is>...>;
std::array<Ret, sizeof...(Is)> a = {{Ret{std::integral_constant<std::size_t, Is>{}}...}};
return a[v.index()];
}(std::make_index_sequence<sizeof...(Ts)>());
}
然后
std::visit([&](auto index){ // index() is constexpr
// ...
}, get_index_variant(v));