counted_iterator doing an unneccessary increment
ericniebler opened this issue · 1 comments
Here's a fun one. This code contains an infinite loop:
auto rng = views::iota(0) | views::filter([](int i) {return i==0;}) | views::take(1);
for (int i : rng)
std::cout << i << std::endl;
It's not easy to see why. view::take::begin()
returns a counted_iterator
that wraps the filter iterator and the integer 1
. When the counted_iterator
is incremented, we do the following:
++current;
--length;
That ++current
causes the filter iterator to look for another integer that is equal to zero, which (obviously) it won't find before the heat death of the universe.
Instead, counted_iterator::operator++
could be specified as:
if (1 == length)
length = 0;
else {
++current;
--length;
}
However, this difference is observable since it changes what counted_iterator::base()
would return for a last-plus-one iterator.
I'm inclined to say this is not a bug, although it is deeply unfortunate. @CaseyCarter, thoughts?
I'm inclined to say this is not a bug, although it is deeply unfortunate.
This is yet another case of "we have to form the past-the-end iterator, so it needs to be valid" a la view::generate(...) | view::take(...)
. I don't think we can or should complicate the design to try to address individual corner cases like this as we come across them.
Notably, fixing this would requires us to touch every counted_iterator
function that modifies or observes current
.