一旦找到所需的替代方案,就突破 std::visit



我经常发现自己使用以下模式从变体容器中获取所需的变体类型:

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;
}

相关内容

  • 没有找到相关文章

最新更新