<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 838: 
   Can an end-of-stream iterator become a non-end-of-stream one?
 </title>
<meta property="og:title" content="Issue 838: 
   Can an end-of-stream iterator become a non-end-of-stream one?
 ">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue838.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++11">C++11</a> status.</em></p>
<h3 id="838"><a href="lwg-defects.html#838">838</a>. 
   Can an <i>end-of-stream</i> iterator become a <i>non-end-of-stream</i> one?
 </h3>
<p><b>Section:</b> 24.6.2 <a href="https://wg21.link/istream.iterator">[istream.iterator]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> Martin Sebor <b>Opened:</b> 2008-05-17 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#istream.iterator">issues</a> in [istream.iterator].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++11">C++11</a> status.</p>
<p><b>Discussion:</b></p>
   <p>

From message c++std-lib-20003...

   </p>
   <p>

The description of <code>istream_iterator</code> in
24.6.2 <a href="https://wg21.link/istream.iterator">[istream.iterator]</a>, p. 1 specifies that objects of the
class become the <i>end-of-stream</i> (EOS) iterators under the
following condition (see also issue <a href="lwg-defects.html#788" title="Ambiguity in [istream.iterator] (Status: C++11)">788</a><sup><a href="https://cplusplus.github.io/LWG/issue788" title="Latest snapshot">(i)</a></sup> another problem
with this paragraph):

   </p>
   <blockquote><p>

If the end of stream is reached (<code>operator void*()</code> on the
stream returns <code>false</code>), the iterator becomes equal to
the <i>end-of-stream</i> iterator value.

   </p></blockquote>
   <p>

One possible implementation approach that has been used in practice is
for the iterator to set its <code>in_stream</code> 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 <i>Effects</i> clause for <code>operator++()</code> says the
iterator unconditionally extracts the next value from the stream by
evaluating <code>*in_stream &gt;&gt; value</code>, without checking
for <code>(in_stream == 0)</code>.

   </p>
   <p>

Conformance to the requirement outlined in the <i>Effects</i> clause
can easily be verified in programs by setting <code>eofbit</code>
or <code>failbit</code> in <code>exceptions()</code> 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.

   </p>
   <p>

Another approach, one that allows <code>operator++()</code> to attempt
to extract the value even for EOS iterators (just as long
as <code>in_stream</code> 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 <i>Effects</i> 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.

   </p>
   <p>

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
stream's <code>eofbit</code> flag has been cleared? That is, are the
assertions in the program below expected to pass?

   </p>
   <blockquote>
     <pre>
   sstream strm ("1 ");
   istream_iterator eos;
   istream_iterator it (strm);
   int i;
   i = *it++
   assert (it == eos);
   strm.clear ();
   strm &lt;&lt; "2 3 ";
   assert (it != eos);
   i = *++it;
   assert (3 == i);
     </pre>
   </blockquote>
   <p>

Or is it intended that once an iterator becomes EOS it stays EOS until
the end of its lifetime?

   </p>
 
 <p><i>[
San Francisco:
]</i></p>


<blockquote>
<p>
We like the direction of the proposed resolution. We're not sure about
the wording, and we need more time to reflect on it,
</p>
<p>
Move to Open. Detlef to rewrite the proposed resolution in such a way
that no reference is made to exposition only members of
<code>istream_iterator</code>.
</p>
</blockquote>

<p><i>[
2009-07 Frankfurt:
]</i></p>


<blockquote><p>
Move to Ready.
</p></blockquote>



 <p id="res-838"><b>Proposed resolution:</b></p>
   <p>

The discussion of this issue on the reflector suggests that the intent
of the standard is for an <code>istreambuf_iterator</code> 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
calling <code>istream_iterator</code> member functions on EOS
iterators whose behavior is in this case undefined.

   </p>
   <p>

To this end we propose to change 24.6.2 <a href="https://wg21.link/istream.iterator">[istream.iterator]</a>, p1,
as follows:

   </p>
   <blockquote><p>

The result of operator-&gt; on an end<ins>-</ins>of<ins>-</ins>stream
is not defined. For any other iterator value a <code>const T*</code>
is returned.<ins> Invoking <code>operator++()</code> on
an <i>end-of-stream</i> iterator is undefined.</ins> It is impossible
to store things into istream iterators...

   </p></blockquote>
   <p>

Add pre/postconditions to the member function descriptions of <code>istream_iterator</code> like so:

   </p>
   <blockquote>

<pre>istream_iterator();</pre>
<p>
<i>Effects</i>: Constructs the <i>end-of-stream</i> iterator.<br/>
<ins><i>Postcondition</i>: <code>in_stream == 0</code>.</ins>
</p>
<pre>istream_iterator(istream_type &amp;s);</pre>
<p>
<i>Effects</i>: Initializes <code>in_stream</code> with &amp;s. value
may be initialized during construction or the first time it is
referenced.<br/>
<ins><i>Postcondition</i>: <code>in_stream == &amp;s</code>.</ins>
</p>
<pre>istream_iterator(const istream_iterator &amp;x);</pre>
<p>
<i>Effects</i>: Constructs a copy of <code>x</code>.<br/>
<ins><i>Postcondition</i>: <code>in_stream == x.in_stream</code>.</ins>
</p>
<pre>istream_iterator&amp; operator++();</pre>
<p>
<ins><i>Requires</i>: <code>in_stream != 0</code>.</ins><br/>
<i>Effects</i>: <code>*in_stream &gt;&gt; value</code>.
</p>
<pre>istream_iterator&amp; operator++(int);</pre>
<p>
<ins><i>Requires</i>: <code>in_stream != 0</code>.</ins><br/>
<i>Effects</i>:
</p>
<blockquote><pre>
istream_iterator tmp (*this);
*in_stream &gt;&gt; value;
return tmp;
     </pre>
     </blockquote>
   </blockquote>
 



</body>
</html>
