当匹配计数大于某个阈值时,我可以使用 C++20 范围来中断吗?
Can I use C++20 ranges to break when matched count is greater than some threshold?
考虑以下预范围代码:
std::vector<int> v(1000*1000);
bool count_gt_5_v1(int val){
return std::count(v.begin(), v.end(), val)>5;
}
它看起来比原始循环更好,但如果 val 在 v 中很常见,它可能会非常低效。
有没有什么方法可以使用 C++20 范围,以便在遇到 val 6 次后停止迭代。 换句话说,我正在寻找一种在满足我的条件时引入中断的方法。 我有这个可恶的东西,这似乎有效,但它比原始的 for 循环丑陋得多。
bool count_gt_5_v2(int val){
int cnt=0;
auto span = std::ranges::views::take_while(v,[&cnt, &val]
(const auto elem)
{
cnt+=elem==val;
return cnt<6;
});
std::ranges::distance(span);
return cnt==6;
}
Link 至完整代码:https://godbolt.org/z/86djdK
你可以这样做:
auto matches = v | rv::filter([=](int i){ return i == val; })
| rv::take(6);
return ranges::distance(matches) == 6;
或者,更好:
auto matches = v | rv::filter([=](int i){ return i == val; });
return not ranges::empty(matches | rv::drop(5));
这次尝试:
std::ranges::views::take_while(v, [&cnt, &val](const auto elem){
cnt+=elem==val;
return cnt<6;
});
不符合take_while
的要求。范围内的所有谓词都必须 等式保持 - 相同的输入,相同的输出。在这里,情况并非如此——如果我们对单个元素调用谓词两次,我们会得到不同的输出。所以这是未定义的行为。