最简单的方法是switch
基于当前的 std::variant::index()
. 这种方法要求您的类型(std::monostate
, A
, B
, C
)始终保持相同的顺序。
// I omitted C to keep the example simpler, the principle is the same
using my_variant = std::variant<std::monostate, A, B>;
void foo(my_variant &v) {
switch (v.index()) {
case 0: break; // do nothing because the type is std::monostate
case 1: {
doSomethingWith(std::get<A>(v));
break;
}
case 2: {
doSomethingElseWith(std::get<B>(v));
break;
}
}
}
如果您的可调用对象适用于任何类型,您还可以使用std::visit
:
void bar(my_variant &v) {
std::visit([](auto &&arg) -> void {
// Here, arg is std::monostate, A or B
// This lambda needs to compile with all three options.
// The lambda returns void because we don't modify the variant, so
// we could also use const& arg.
}, v);
}
如果您不想std::visit
接受std::monostate
,则只需检查 是否index
为 0。再一次,这依赖于std::monostate
变体的第一个类型,因此最好始终将其设为第一个。
if-constexpr
您还可以在可调用内部检测类型。使用这种方法,参数不必再以相同的顺序排列:
void bar(my_variant &v) {
std::visit([](auto &&arg) -> my_variant {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<std::monostate, T>) {
return arg; // arg is std::monostate here
}
else if constexpr (std::is_same_v<A, T>) {
return arg + arg; // arg is A here
}
else if constexpr (std::is_same_v<B, T>) {
return arg * arg; // arg is B here
}
}, v);
}
请注意,第一个 lambda 会返回void
,因为它只处理变量的当前值。如果你想修改变体,你的 lambda 需要my_variant
再次返回。
您可以在内部使用重载的访问者std::visit
来处理A
或B
单独处理。有关std::visit
更多示例,请参阅。