Section: 27.6.1 [istream.iterator] Status: C++11 Submitter: Martin Sebor Opened: 2008-05-17 Last modified: 2016-02-10
Priority: Not Prioritized
View all other issues in [istream.iterator].
View all issues with C++11 status.
From message c++std-lib-20003...
The description of
27.6.1 [istream.iterator], p. 1 specifies that objects of the
class become the end-of-stream (EOS) iterators under the
following condition (see also issue 788 another problem
with this paragraph):
If the end of stream is reached (
operator void*()on the stream returns
false), the iterator becomes equal to the end-of-stream iterator value.
One possible implementation approach that has been used in practice is
for the iterator to set its
in_stream pointer to 0 when
it reaches the end of the stream, just like the default ctor does on
initialization. The problem with this approach is that
the Effects clause for
operator++() says the
iterator unconditionally extracts the next value from the stream by
*in_stream >> value, without checking
(in_stream == 0).
Conformance to the requirement outlined in the Effects clause
can easily be verified in programs by setting
exceptions() of the associated
stream and attempting to iterate past the end of the stream: each
past-the-end access should trigger an exception. This suggests that
some other, more elaborate technique might be intended.
Another approach, one that allows
operator++() to attempt
to extract the value even for EOS iterators (just as long
in_stream is non-0) is for the iterator to maintain a
flag indicating whether it has reached the end of the stream. This
technique would satisfy the presumed requirement implied by
the Effects clause mentioned above, but it isn't supported by
the exposition-only members of the class (no such flag is shown). This
approach is also found in existing practice.
The inconsistency between existing implementations raises the question
of whether the intent of the specification is that a non-EOS iterator
that has reached the EOS become a non-EOS one again after the
eofbit flag has been cleared? That is, are the
assertions 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 until the end of its lifetime?
[ San Francisco: ]
We like the direction of the proposed resolution. We're not sure about the wording, and we need more time to reflect on it,
Move to Open. Detlef to rewrite the proposed resolution in such a way that no reference is made to exposition only members of istream_iterator.
[ 2009-07 Frankfurt: ]
Move to Ready.
The discussion of this issue on the reflector suggests that the intent
of the standard is for an
istreambuf_iterator that has
reached the EOS to remain in the EOS state until the end of its
lifetime. Implementations that permit EOS iterators to return to a
non-EOS state may only do so as an extension, and only as a result of
istream_iterator member functions on EOS
iterators whose behavior is in this case undefined.
To this end we propose to change 27.6.1 [istream.iterator], p1, as follows:
The result of operator-> on an endofstream is not defined. For any other iterator value a
const T*is returned. It is impossible to store things into istream iterators...
Add pre/postconditions to the member function descriptions of
istream_iterator like so:
Effects: Constructs the end-of-stream iterator.
in_streamwith &s. value may be initialized during construction or the first time it is referenced.
istream_iterator(const istream_iterator &x);
Effects: Constructs a copy of
*in_stream >> value.istream_iterator& operator++(int);
Effects:istream_iterator tmp (*this); *in_stream >> value; return tmp;