访问 std::variant 时获取其编译时索引?

问题描述 投票:0回答:1

我有一个

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
版本)之外,还有其他更简单的方法可以实现我想要的功能,而无需通过索引执行多次查找吗?

c++ c++20 template-meta-programming variant std-variant
1个回答
0
投票

我会在索引上使用

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

演示

© www.soinside.com 2019 - 2024. All rights reserved.