neo*_*nxc 2 c++ c++20 std-ranges
C++20 标准在[range.adaptors.general]中表示范围适配器
当迭代结果视图时延迟评估。
另一方面,在[range.filter.view]中,filter_view 的 begin 函数有一个注释,提到了缓存结果。那么适配器的懒惰程度如何呢?
当执行以下代码时:
#include <iostream>
#include <ranges>
void print(std::ranges::range auto&& r)
{
for (const auto& item : r)
{
std::cout << item << ", ";
}
std::cout << " <end of range>\n";
}
int main()
{
using namespace std::ranges;
bool filter = false;
auto v = iota_view{4, 10} | views::filter([&filter](auto item){return filter;});
// multipass guarantee
static_assert(std::ranges::forward_range<decltype(v)>);
filter = true;
print(v);
filter = false;
print(v);
filter = true;
print(v);
}
Run Code Online (Sandbox Code Playgroud)
是否保证适配器会尊重filter变量的值?如果不是,我正在调用什么样的行为以及在哪里声明?
请记住,在 C++ 迭代器模型中,定位和访问是两个不同的操作。然而,过滤迭代器是一种其位置基于访问其正在过滤的范围的迭代器。这就是迭代器的本质。
要查找过滤范围的开头,需要找到基础范围中与过滤条件匹配的第一个位置。就像在过滤范围中查找下一个元素需要迭代一样,直到到达与过滤条件匹配的另一个迭代器。
因此,获取过滤范围的起始迭代器需要访问该范围的至少一个元素。过滤迭代器在完成其工作的同时尽可能地惰性。
但是,您的特定代码表现出 UB,因为您的谓词不是regular_invocable. 该标准明确要求:
invoke 函数调用表达式应保持相等性 ( [concepts.equality] )
这意味着:
如果给定相同的输入,则表达式会产生相同的输出,则该表达式是保持相等的。表达式的输入是表达式操作数的集合。表达式的输出是表达式的结果和表达式修改的所有操作数。
您通过更改谓词的行为违反了该要求。
| 归档时间: |
|
| 查看次数: |
577 次 |
| 最近记录: |