【发布时间】:2019-08-24 23:06:11
【问题描述】:
我有一些变体using V = std::variant<A, B, C> 和一个带有原型V parse(const json&) 的函数。该函数应该尝试解析所有类型(例如A、B,然后是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");
}
但它肯定会被简化,因为 lambdas 仅在类型上有所不同,而我真正需要的是迭代 std::variant 的类型。
【问题讨论】:
-
除非我误解了你的需要,
std::visit应该可以工作。如果变量未初始化,则不应解析它。如果您只是说没有价值,那是一种特殊情况(请参阅std::variant::valueless_by_exception) -
@CruzJean,在我看来,OP 想要构建变体。没有什么可访问的,因为它还没有被创建,它是从函数返回的东西。
-
@chris 解析函数正在为
j上的各种T类型调用get<std::optional<T>>,即i_j,输入json对象。那不应该已经初始化了吗?我们返回的只是第一次成功调用解析器的结果(*只是取消引用std::optional) -
@CruzJean,问题是如何提供所有这些解析功能,而无需再次明确列出每种类型(A、B、C)。函数如何进行解析并不太相关,除了它们有一个清晰的模式,这有助于从变体的类型自动生成它们。检查第一个有效结果的代码很好。
-
@chris 但如果它与
std::visit兼容,则可以使用通用访问者并直接返回 A、B、C 实例(或不返回等)。这将避免指定 anywhere 类型的 any
标签: c++ c++17 template-meta-programming variant nlohmann-json