views
在一个简单的适配器管道中,gen
调用了一个函数来生成一系列值(使用内部状态),然后对其进行过滤。
令人惊讶和违反直觉的(至少对我而言)是生成器函数在每次迭代中被调用两次,因此对同一过滤器的下一次检查失败(过滤后的值不会在管道中重用)。
您知道这是否是正确的预期行为(以及为什么)?
在 GCC 10.3、11.1libstdc++
和中继(代码)和range-v3
GCC 和铿锵声(代码)中进行了测试。
int main() {
int n = 0;
auto gen = [&n]() {
auto result = ++n;
std::cout << "Generate [" << result << "]\n";
return result;
};
auto tmp =
ranges::views::iota(0)
| ranges::views::transform([gen](auto &&) { return gen(); })
| ranges::views::filter([](auto &&i) {
std::cout << "#1 " << i << " " << (i % 2) << "\n";
return (i % 2) == 1;
});
for (auto &&i : tmp | ranges::views::take(1)) {
std::cout << "#2 " << i << " " << ((i % 2) == 1) << "\n";
assert(((i % 2) == 1));
}
}
注意:如果gen
函数被编写为具有内部状态的可变函数,则它不会编译:
auto gen = [n=0]() mutable {
auto result = ++n;
std::cout << "Generate [" << result << "]\n";
return result;
};
(而且我知道纯函数更好)