<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 788: Ambiguity in [istream.iterator]</title>
<meta property="og:title" content="Issue 788: Ambiguity in [istream.iterator]">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue788.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="788"><a href="lwg-defects.html#788">788</a>. Ambiguity in [istream.iterator]</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-02-06 <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><b>Addresses UK 287</b></p>

<blockquote>
<p>
It is not clear what the initial state of an <code>istream_iterator</code> should be. Is
_value_ initialized by reading the stream, or default&#47;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?
</p>

<p>
Recommendation: Specify _value_ is initialized by reading the stream, or
the iterator takes on the end-of-stream value if the stream is empty.
</p>
</blockquote>

<p>
The description of how an istream_iterator object becomes an
end-of-stream iterator is a) ambiguous and b) out of date WRT
issue <a href="lwg-defects.html#468" title="unexpected consequences of ios_base::operator void*() (Status: CD1)">468</a><sup><a href="https://cplusplus.github.io/LWG/issue468" title="Latest snapshot">(i)</a></sup>:
</p>

<blockquote><p>
<code>istream_iterator</code> reads (using <code>operator&gt;&gt;</code>) successive elements from the
input stream for which it was constructed. After it is constructed, and
every time <code>++</code> is used, the iterator reads and stores a value of <code>T</code>. 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.
The constructor with no arguments <code>istream_iterator()</code> always constructs
an end of stream input iterator object, which is the only legitimate
iterator to be used for the end condition. The result of <code>operator*</code> on an
end of stream is not defined. For any other iterator value a <code>const T&amp;</code> is
returned. The result of <code>operator-&gt;</code> on an end of stream is not defined.
For any other iterator value a <code>const T*</code> is returned. It is impossible to
store things into istream iterators. The main peculiarity of the istream
iterators is the fact that <code>++</code> operators are not equality preserving,
that is, <code>i == j</code> does not guarantee at all that <code>++i == ++j</code>. Every time <code>++</code>
is used a new value is read.
</p></blockquote>

<p>
<code>istream::operator void*()</code> returns null if <code>istream::fail()</code> is <code>true</code>,
otherwise non-null. <code>istream::fail()</code> returns <code>true</code> if <code>failbit</code> or
<code>badbit</code> is set in <code>rdstate()</code>. Reaching the end of stream doesn't
necessarily imply that <code>failbit</code> or <code>badbit</code> is set (e.g., after
extracting an <code>int</code> from <code>stringstream("123")</code> the stream object will
have reached the end of stream but <code>fail()</code> is <code>false</code> and <code>operator
void*()</code> will return a non-null value).
</p>

<p>
Also I would prefer to be explicit about calling <code>fail()</code> here
(there is no <code>operator void*()</code> anymore.)
</p>

<p><i>[
Summit:
]</i></p>


<blockquote><p>
Moved from Ready to Open for the purposes of using this issue to address NB UK 287.
Martin to handle.
</p></blockquote>

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


<blockquote>
<p>
This improves the wording.
</p>
<p>
Move to Ready.
</p>
</blockquote>



<p id="res-788"><b>Proposed resolution:</b></p>
<p>
Change 24.6.2 <a href="https://wg21.link/istream.iterator">[istream.iterator]</a>/1:
</p>

<blockquote><p>
<code>istream_iterator</code> reads (using <code>operator&gt;&gt;</code>) successive elements from the
input stream for which it was constructed. After it is constructed, and
every time <code>++</code> is used, the iterator reads and stores a value of <code>T</code>. If
<del>the end of stream is reached</del> <ins>the iterator fails to read and store a value of <code>T</code></ins>
(<code><del>operator void*()</del> <ins>fail()</ins></code> on the stream returns
<code><del>false</del> <ins>true</ins></code>), the iterator becomes equal to the <i>end-of-stream</i> iterator value.
The constructor with no arguments <code>istream_iterator()</code> always constructs
an end of stream input iterator object, which is the only legitimate
iterator to be used for the end condition. The result of <code>operator*</code> on an
end of stream is not defined. For any other iterator value a <code>const T&amp;</code> is
returned. The result of <code>operator-&gt;</code> on an end of stream is not defined.
For any other iterator value a <code>const T*</code> is returned. It is impossible to
store things into istream iterators. The main peculiarity of the istream
iterators is the fact that <code>++</code> operators are not equality preserving,
that is, <code>i == j</code> does not guarantee at all that <code>++i == ++j</code>. Every time <code>++</code>
is used a new value is read.
</p></blockquote>





</body>
</html>
