gpt4 book ai didi

c++ - 如何迭代 std::variant 的类型?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:33:10 25 4
gpt4 key购买 nike

我有一些变体 using V = std::variant<A, B, C>和一个带有原型(prototype)的函数 V parse(const json&) .该函数应该尝试解析所有类型(例如 AB ,然后是 C )直到第一次成功(它应该隐式地解析,因为及时会有很多类型)。

如何实现这种东西?

我们可以使用 std::variant_size不知何故。

Here是接近我需要的东西。

我的解决方案是明确列出所有类型的解析器。

V parse(const json& i_j)
{
using Parser = std::function<MaybeV(const json&)>;
static const auto ps = std::vector<Parser>{
[](const auto& j)->MaybeV{return j.get<std::optional<A>>;},
[](const auto& j)->MaybeV{return j.get<std::optional<B>>;},
[](const auto& j)->MaybeV{return j.get<std::optional<C>>;}
};
for (const auto& p : ps)
if (auto opt_result = p(i_j))
return std::move(*opt_result);
throw ParseError("Can't parse");
}

但它肯定可以简化,因为 lambda 仅在类型上不同,而我实际需要的是迭代 std::variant 的类型.

最佳答案

您需要从 0 到变体大小减 1 的编译时整数,并且可能提前退出对它们的迭代。

有很多方法可以获取编译时整数。我最喜欢的两个是生成整型常量元组,或者使用整型常量参数包调用延续。

以整数常量版本的元组为例,您可以使用“每个元组”依次访问每个。

template<std::size_t I>
using index_t = std::integral_constant<std::size_t, I>;
template<std::size_t I>
constexpr index_t<I> index{};

template<std::size_t...Is>
constexpr std::tuple< index_t<Is>... > make_indexes(std::index_sequence<Is...>){
return std::make_tuple(index<Is>...);
}
template<std::size_t N>
constexpr auto indexing_tuple = make_indexes(std::make_index_sequence<N>{});

根据您所说的变体尺寸。从中调用 tuple_foreach。

如果解析成功但尚未解析,tuple_foreach 会放置可选的返回值。

V parse(const json& j)
{
auto indexes = indexing_tuple<tuple_size_v<V>>;
std::optional<V> retval;
tuple_foreach(indexes, [&](auto I){ // I is compile time integer
if(retval) return;
auto p = j.get<tuple_alternative_t<I>>();
if(p) retval.emplace(std::move(*p));
});
if(!retval) throw ParseError("Can't parse");
return std::move(*retval);
}

tuple_foreach 可以在网上找到,但是为了完整起见:

template<std::size_t...Is, class T, class F>
auto tuple_foreach( std::index_sequence<Is...>, T&& tup, F&& f ) {
( f( std::get<Is>( std::forward<T>(tup) ) ), ... );
}
template<class T, class F>
auto tuple_foreach( T&& tup, F&& f ) {
auto indexes = std::make_index_sequence< std::tuple_size_v< std::decay_t<T> > >{};
return tuple_foreach( indexes, std::forward<T>(tup), std::forward<F>(f) );
}

应该在 中执行.

关于c++ - 如何迭代 std::variant 的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57642102/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com