Here in a simple pipeline of views
adaptors, there is the gen
function called to generate a sequence of values (using an internal state) and then a filter on it.
What is surprising and counterintuitive (at least for me) is the fact that the generator function is called twice at each iteration, so that the next check on the same filter fails (the filtered value is not reused in the pipeline).
Do you have an idea if this is the correct expected behavior (and why)?
Tested with libstdc++
in GCC 10.3, 11.1 & trunk (code) and range-v3
with GCC & clang (code).
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));
}
}
NB: if gen
function is written as mutable with an internal state, it does not compile:
auto gen = [n=0]() mutable {
auto result = ++n;
std::cout << "Generate [" << result << "]\n";
return result;
};
(and I know that pure functions are better)