This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.
Section: 24.6.2 [istream.iterator] Status: C++11 Submitter: Martin Sebor Opened: 2008-02-06 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [istream.iterator].
View all issues with C++11 status.
Discussion:
Addresses UK 287
It is not clear what the initial state of an
istream_iterator
should be. Is _value_ initialized by reading the stream, or default/value initialized? If it is initialized by reading the stream, what happens if the initialization is deferred until first dereference, when ideally the iterator value should have been that of an end-of-stream iterator which is not safely dereferencable?Recommendation: Specify _value_ is initialized by reading the stream, or the iterator takes on the end-of-stream value if the stream is empty.
The description of how an istream_iterator object becomes an end-of-stream iterator is a) ambiguous and b) out of date WRT issue 468(i):
istream_iterator
reads (usingoperator>>
) successive elements from the input stream for which it was constructed. After it is constructed, and every time++
is used, the iterator reads and stores a value ofT
. If the end of stream is reached (operator void*()
on the stream returnsfalse
), the iterator becomes equal to the end-of-stream iterator value. The constructor with no argumentsistream_iterator()
always constructs an end of stream input iterator object, which is the only legitimate iterator to be used for the end condition. The result ofoperator*
on an end of stream is not defined. For any other iterator value aconst T&
is returned. The result ofoperator->
on an end of stream is not defined. For any other iterator value aconst T*
is returned. It is impossible to store things into istream iterators. The main peculiarity of the istream iterators is the fact that++
operators are not equality preserving, that is,i == j
does not guarantee at all that++i == ++j
. Every time++
is used a new value is read.
istream::operator void*()
returns null if istream::fail()
is true
,
otherwise non-null. istream::fail()
returns true
if failbit
or
badbit
is set in rdstate()
. Reaching the end of stream doesn't
necessarily imply that failbit
or badbit
is set (e.g., after
extracting an int
from stringstream("123")
the stream object will
have reached the end of stream but fail()
is false
and operator
void*()
will return a non-null value).
Also I would prefer to be explicit about calling fail()
here
(there is no operator void*()
anymore.)
[ Summit: ]
Moved from Ready to Open for the purposes of using this issue to address NB UK 287. Martin to handle.
[ 2009-07 Frankfurt: ]
This improves the wording.
Move to Ready.
Proposed resolution:
Change 24.6.2 [istream.iterator]/1:
istream_iterator
reads (usingoperator>>
) successive elements from the input stream for which it was constructed. After it is constructed, and every time++
is used, the iterator reads and stores a value ofT
. Ifthe end of stream is reachedthe iterator fails to read and store a value ofT
(on the stream returns
operator void*()fail()), the iterator becomes equal to the end-of-stream iterator value. The constructor with no arguments
falsetrueistream_iterator()
always constructs an end of stream input iterator object, which is the only legitimate iterator to be used for the end condition. The result ofoperator*
on an end of stream is not defined. For any other iterator value aconst T&
is returned. The result ofoperator->
on an end of stream is not defined. For any other iterator value aconst T*
is returned. It is impossible to store things into istream iterators. The main peculiarity of the istream iterators is the fact that++
operators are not equality preserving, that is,i == j
does not guarantee at all that++i == ++j
. Every time++
is used a new value is read.