Closed benjamind2330 closed 2 months ago
range-v3 doesn't support so-called "stashing" iterators. neither do the c++20 ranges concepts. if it works in your stdlib that's cool, but don't rely on it.
@ericniebler This is genuinly excellent to know. We have been relying on it, but I will make efforts to move away from this. I'm interested, do you happen to know if this is specified somewhere? Our iterator meets the requirements for a forward iterator I thought, so I am surprised that it is not supported.
Stashing iterators are perfectly good input iterators, but they can't meet the multipass requirements for forward-and-stronger iterator types.
The "old" iterator requirements specify that *i
and *j
for forward iterators i
and j
must refer to the same object if and only if i == j
is true
([forward.iterators]/6). This obviously can't hold for a stashing iterator since *i
and *auto{i}
refer to different objects.
For the C++20 forward_iterator
concept we complicated things by relaxing the requirement that decltype(*i)
is always a reference type, so *i
doesn't always refer to an object. We have the more general requirement that "Pointers and references obtained from a forward iterator into a range [i, s)
shall remain valid while [i, s)
continues to denote a range."([iterator.concept.forward]/3](https://eel.is/c++draft/iterator.concept.forward#3)). That means that things like:
if (std::distance(i, j) >= 2) {
auto&& ref = *std::next(i);
do_something(ref);
}
have to work, which won't if ref
is bound to a subobject of the iterator returned from std::next
that is destroyed at the semicolon before the do_something
call.
In this example i have made a simple iterator that represents a larger problem. Namely that the iterator is using the container to modify and output a member variable.
Here is a live example https://godbolt.org/z/8dEh7a8cK
The issue appears to be that this function:
Takes arguments by value leading to a copy of the iterator then a dangling reference to its internals.
This does not happen in std::ranges::views.
I think this might be a bug, should it be:
?