我有一个变量 using V = std::variant<A, B, C>
,以及一个原型为 V parse(const json&)
的函数。该函数应尝试解析所有类型(例如 A、B,然后 C),直到第一个成功(并且这应该是隐式的,因为时间中会有许多类型)。
如何实现这种功能?
我们可以使用 std::variant_size
来实现。
这里 有一些接近我需要的东西。
我的解决方案是显式列出所有类型的解析器。
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
类型。
std::visit
应该可以胜任。如果变量未初始化,则不应对其进行解析。如果您只是指没有值,那么这是一个特殊情况(请参见std::variant::valueless_by_exception
)。 - Cruz Jeanj
上的各种T
类型的get<std::optional<T>>
,其中j
是i_j
,即输入的json
对象。这不应该已经初始化了吗?我们返回的只是第一个成功的解析器调用的结果(*
只是取消引用std::optional
)。 - Cruz Jeanstd::visit
兼容,那么可以使用通用访问器直接返回A、B、C实例(或在没有匹配时抛出异常等)。这样就可以避免在任何地方指定任何类型。 - Cruz Jean.get<optional<T>>
,但不能直接返回访问结果。也就是说,你可以有一个从“int”构造的类型“A”,但如果你访问json并得到一个“int”,你仍然必须通过“A”、“B”和“C”来检查是否可以从该“int”构造它们。如果你不打算访问json对象,那么我不确定你建议访问什么。 - chris