Reputation: 59
I was reading The C++ Programming Language 4th edition by Bjarne Stroustrup. In the iterator chapter (Chapter 31.1.2), it says:
Input iterator: We can iterate forward using ++ and read each element (repeatedly) using *.
Output iterator: We can iterate forward using ++ and write an element once only using *.
I have done many searches on whether input iterator can be read only once or repeatedly, for example: http://www.cplusplus.com/reference/iterator/InputIterator/ https://www.geeksforgeeks.org/input-iterators-in-cpp/
and most suggests that input iterator can be read once only. But why the author says repeatedly for the input iterator? Is this correct? And if so, why input iterator can be read repeatedly but output iterator can only be written once. I always thought input and output iterator are completely opposite of each other.
Thanks everyone!
Upvotes: 3
Views: 1155
Reputation: 238311
The book is correct; and the contradicting sources are not. There appears to be no rule that disallows reading an object more than once by indirecting through an input iterator.
The other sources may be confused by another similar limitation which is that once input iterator has been incremented, all copies of the previous iterator are invalidated, and thus may not be indirected anymore. This limitation is shared by output iterators. By example:
value = *inputIt;
value = *inputIt; // OK
copyIt = inputIt;
++inputIt;
value = *copyIt; // Not OK
The book is also correct that output iterator does have the limitation:
*outputIt = value;
++outputIt;
*outputIt = value; // OK
*outputIt = value; // Not OK
I always thought input and output iterator are completely opposite of each other.
Many output iterators are also input iterators, so "opposite" isn't exactly very descriptive. They are partially overlapping sets of requirements. An iterator can meet both sets of requirements.
If we have *outputIt = 1; then *outputIt = 2; aren't we just assigning to the same *outputit twice?
Yes; And that's something that output iterators are not required to support.
Consider for example an output iterator that sends packets over the internet. You've written a packet, and it has been sent to the internet and received by some other machine. You can't travel back in time and decide that the packet that was sent is something different. You must move on to the next packet and send that instead.
Upvotes: 3
Reputation: 76245
You can read through an input iterator as many times as you want to. That comes from the requirement that "(void)*a, *a
is equivalent to *a
" [input.iterators], see table.
You can only write through an output iterator once. For *r = o
, "After this operation r
is not required to be dereferenceable". [output.iterators], see table. After you increment r
you have a new iterator, and you can again assign through it once.
Once you combine these two into a forward iterator, the restriction on multiple assignments through the same iterator goes away.
Upvotes: 1
Reputation: 180414
Bjarne's quote is correct. If you have an input iterator you can do *iterator
as many times as you want. If you have an output iterator you can only do *iterator
once.
What they both have in common though is they can only be used in single pass algorithms. Once you increment either an input or output iterator then an iterator to a previous position is no longer required to be dereferenceable
That means in
while (iterator != end)
{
if (*iterator == some_value)
something = *iterator;
++iterator;
}
iterator
has to be an input iterator since we dereference it twice each iteration. On the other hand
while (iterator != end)
{
something = *iterator;
++iterator;
}
works for both an input and output iterators since we do only a single dereference.
Upvotes: 2