我经常发现自己使用以下模式从变体容器中获取所需的变体类型:
for(auto&& Variant : variantContainer)
{
// If the variant types match, do something
std::visit([this, &Variant](auto&& arg)
{
using argType = typename std::decay_t<decltype(arg)>; // e.g. `Field<int>`
if (std::holds_alternative<argType>(Variant)) // if the current variant has the same type as the field
{
// do something, then preferably stop checking
// the other possible variants
}
}, Variant);
}
但是,根据cpp首选项.com关于std::visit
复杂性的声明:
如果变体数大于 1,则可调用对象的调用没有复杂性要求。
这可能是典型的线性复杂性,所以我想知道一旦我从中获得我需要的东西,是否有任何机制可以尽早摆脱std::visit
?
我想不出一种方法,您可以在不明确检查返回值之类的东西的情况下通知std::visit
您希望"突破",而无需std::visit
明确检查返回值之类的内容。例如,假设visit
的自定义版本需要"特殊"返回类型:
struct visitor
{
auto operator()(int, int) { return continue_{}; }
auto operator()(int, float) { return break_{}; }
auto operator()(float, int) { return continue_{}; }
auto operator()(float, float) { return continue_{}; }
};
它的实现将能够检测调用的visitor::operator()
重载是否返回continue_
或break_
并停止。
无论如何,我认为你不应该太担心:
libc++
通过创建函数指针的constexpr
矩阵,然后调用匹配的函数指针来实现多变量访问。libstdc++
似乎通过生成多维"vtable"来做类似的事情。
一种方法是通过引用捕获中断标志。
// surely you don't want a copy?
for(auto&& Variant : variantContainer)
{
auto should_break = false;
// If the variant types match, set the value
std::visit([this, &should_break](auto&& arg)
{
// arg is one of the Ts... in the variant
this->doTheRightThing(arg);
if (shouldCauseBreak(arg))
should_break = true;
}, Variant);
if (should_break)
break;
}