This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofC++11 status.
Section: 24.6.2[istream.iterator]Status:C++11Submitter: Martin SeborOpened: 2008-05-17Last modified: 2016-01-28
Priority:Not Prioritized
View all otherissues in [istream.iterator].
View all issues withC++11 status.
Discussion:
From message c++std-lib-20003...
The description ofistream_iterator in24.6.2[istream.iterator], p. 1 specifies that objects of theclass become theend-of-stream (EOS) iterators under thefollowing condition (see also issue788(i) another problemwith this paragraph):
If the end of stream is reached (
operator void*()on thestream returnsfalse), the iterator becomes equal totheend-of-stream iterator value.
One possible implementation approach that has been used in practice isfor the iterator to set itsin_stream pointer to 0 whenit reaches the end of the stream, just like the default ctor does oninitialization. The problem with this approach is thattheEffects clause foroperator++() says theiterator unconditionally extracts the next value from the stream byevaluating*in_stream >> value, without checkingfor(in_stream == 0).
Conformance to the requirement outlined in theEffects clausecan easily be verified in programs by settingeofbitorfailbit inexceptions() of the associatedstream and attempting to iterate past the end of the stream: eachpast-the-end access should trigger an exception. This suggests thatsome other, more elaborate technique might be intended.
Another approach, one that allowsoperator++() to attemptto extract the value even for EOS iterators (just as longasin_stream is non-0) is for the iterator to maintain aflag indicating whether it has reached the end of the stream. Thistechnique would satisfy the presumed requirement implied bytheEffects clause mentioned above, but it isn't supported bythe exposition-only members of the class (no such flag is shown). Thisapproach is also found in existing practice.
The inconsistency between existing implementations raises the questionof whether the intent of the specification is that a non-EOS iteratorthat has reached the EOS become a non-EOS one again after thestream'seofbit flag has been cleared? That is, are theassertions in the program below expected to pass?
sstream strm ("1 "); istream_iterator eos; istream_iterator it (strm); int i; i = *it++ assert (it == eos); strm.clear (); strm << "2 3 "; assert (it != eos); i = *++it; assert (3 == i);Or is it intended that once an iterator becomes EOS it stays EOS untilthe end of its lifetime?
[San Francisco:]
We like the direction of the proposed resolution. We're not sure aboutthe wording, and we need more time to reflect on it,
Move to Open. Detlef to rewrite the proposed resolution in such a waythat no reference is made to exposition only members of
istream_iterator.
[2009-07 Frankfurt:]
Move to Ready.
Proposed resolution:
The discussion of this issue on the reflector suggests that the intentof the standard is for anistreambuf_iterator that hasreached the EOS to remain in the EOS state until the end of itslifetime. Implementations that permit EOS iterators to return to anon-EOS state may only do so as an extension, and only as a result ofcallingistream_iterator member functions on EOSiterators whose behavior is in this case undefined.
To this end we propose to change 24.6.2[istream.iterator], p1,as follows:
The result of operator-> on an end-of-streamis not defined. For any other iterator value a
const T*is returned. Invokingoperator++()onanend-of-stream iterator is undefined. It is impossibleto store things into istream iterators...
Add pre/postconditions to the member function descriptions ofistream_iterator like so:
istream_iterator();Effects: Constructs theend-of-stream iterator.
Postcondition:in_stream == 0.istream_iterator(istream_type &s);Effects: Initializes
in_streamwith &s. valuemay be initialized during construction or the first time it isreferenced.
Postcondition:in_stream == &s.istream_iterator(const istream_iterator &x);Effects: Constructs a copy of
x.
Postcondition:in_stream == x.in_stream.istream_iterator& operator++();Requires:
in_stream != 0.
Effects:*in_stream >> value.istream_iterator& operator++(int);Requires:
in_stream != 0.
Effects:istream_iterator tmp (*this);*in_stream >> value;return tmp;