I'm implementing an iterator that iterates over the results of a generator function rather than over a data structure in memory such as a vector or map.
Reading through the final working draft for C++17 §27.2.3, the return type of the dereference operator for an input iterator (and by extension, most other iterators) a forward iterator is required to be a reference. This is fine for items that exist in the data structure the iterator is iterating over. However, because I'm not using a data structure and am calculating each item when the dereference operator is called, I don't have a valid reference to return; the calculated item is destroyed when the operator returns. To work around this, I am storing the result of the calculation in the iterator itself and returning a reference to the stored result. This works fine for my use case, but has issues of its own when used with arbitrary user-defined types.
I can understand iterators being allowed to return a reference, but why would this be a requirement for non-mutating iterators? Did the writers of the standard not consider generators and on-the-fly transformations to be valid use cases for iterators? Would returning a value instead of a const reference cause any actual harm?
[edit]: I'm asking more out of curiosity about why the standard is written the way it is, since I already have a perfectly good workaround.
3, the return type of the dereference operator for an input iterator (and by extension, most other iterators) a forward iterator is required to be a reference. This is fine for items that exist in the data structure the iterator is iterating over.
An iterator is an object that allows you to step through the contents of another object, by providing convenient operations for getting the first element, testing when you are done, and getting the next element if you are not. In C, we try to design iterators to have operations that fit well in the top of a for loop.
Introduction to Iterators in C++ An iterator is an object (like a pointer) that points to an element inside the container. We can use iterators to move through the contents of the container.
The iterator is implemented as a pointer to a node, and contains operator overloads for the four usual iterator operations of dereference, increment, comparison, and assignment. in the list class that can be used to insert new data items at arbitrary locations in the list.
Dereferencing an input iterator is not required to yield a glvalue (that is, return a reference). The input iterator requirements say that the return type when dereferencing must be "reference
, convertible to T
" but nowhere does it say that reference
must be a reference type.
However, dereferencing a forward iterator is required to yield a glvalue:
if
X
is a mutable iterator,reference
is a reference toT
; ifX
is a constant iterator,reference
is a reference toconst T
,
So go ahead and write your iterator that generates elements on the fly, but it can only be an input iterator, not a forward iterator. For many algorithms this is sufficient (e.g., std::for_each
and std::all_of
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With