<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 696: istream::operator&gt;&gt;(int&amp;) broken</title>
<meta property="og:title" content="Issue 696: istream::operator&gt;&gt;(int&amp;) broken">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue696.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="696"><a href="lwg-defects.html#696">696</a>. <code>istream::operator&gt;&gt;(int&amp;)</code> broken</h3>
<p><b>Section:</b> 31.7.5.3.2 <a href="https://wg21.link/istream.formatted.arithmetic">[istream.formatted.arithmetic]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> Martin Sebor <b>Opened:</b> 2007-06-23 <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.formatted.arithmetic">issues</a> in [istream.formatted.arithmetic].</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-17897:
</p>
<p>
The code shown in 31.7.5.3.2 <a href="https://wg21.link/istream.formatted.arithmetic">[istream.formatted.arithmetic]</a> as the "as if"
implementation of the two arithmetic extractors that don't have a
corresponding <code>num_get</code> interface (i.e., the
<code>short</code> and <code>int</code> overloads) is subtly buggy in
how it deals with <code>EOF</code>, overflow, and other similar
conditions (in addition to containing a few typos).
</p>
<p>
One problem is that if <code>num_get::get()</code> reaches the EOF
after reading in an otherwise valid value that exceeds the limits of
the narrower type (but not <code>LONG_MIN</code> or
<code>LONG_MAX</code>), it will set <code><i>err</i></code> to
<code>eofbit</code>. Because of the if condition testing for
<code>(<i>err</i> == 0)</code>, the extractor won't set
<code>failbit</code> (and presumably, return a bogus value to the
caller).
</p>
<p>
Another problem with the code is that it never actually sets the
argument to the extracted value. It can't happen after the call to
<code>setstate()</code> since the function may throw, so we need to
show when and how it's done (we can't just punt as say: "it happens
afterwards"). However, it turns out that showing how it's done isn't
quite so easy since the argument is normally left unchanged by the
facet on error except when the error is due to a misplaced thousands
separator, which causes <code>failbit</code> to be set but doesn't
prevent the facet from storing the value.
</p>

<p><i>[
Batavia (2009-05):
]</i></p>

<blockquote>
<p>
We believe this part of the Standard has been recently adjusted
and that this issue was addressed during that rewrite.
</p>
<p>
Move to NAD.
</p>
</blockquote>

<p><i>[
2009-05-28 Howard adds:
]</i></p>


<blockquote>
<p>
I've moved this issue from Tentatively NAD to Open.
</p>

<p>
The current wording of
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2857.pdf">N2857</a>
in 28.3.4.3.2.3 <a href="https://wg21.link/facet.num.get.virtuals">[facet.num.get.virtuals]</a> p3, stage 3 appears to indicate that
in parsing arithmetic types, the value is always set, but sometimes in addition
to setting <code>failbit</code>.
</p>

<ul>
<li>
If there is a range error, the value is set to min or max, else
</li>
<li>
if there is a conversion error, the value is set to 0, else
</li>
<li>
if there is a grouping error, the value is set to whatever it would be if grouping were ignored, else
</li>
<li>
the value is set to its error-free result.
</li>
</ul>

<p>
However there is a contradictory sentence in 28.3.4.3.2.3 <a href="https://wg21.link/facet.num.get.virtuals">[facet.num.get.virtuals]</a> p1.
</p>

<p>
31.7.5.3.2 <a href="https://wg21.link/istream.formatted.arithmetic">[istream.formatted.arithmetic]</a> should mimic the behavior of 28.3.4.3.2.3 <a href="https://wg21.link/facet.num.get.virtuals">[facet.num.get.virtuals]</a>
(whatever we decide that behavior is) for
<code>int</code> and <code>short</code>, and currently does not.  I believe that the
correct code fragment should look like:
</p>

<blockquote><pre>
typedef num_get&lt;charT,istreambuf_iterator&lt;charT,traits&gt; &gt; numget;
iostate err = ios_base::goodbit;
long lval;
use_facet&lt;numget&gt;(loc).get(*this, 0, *this, err, lval);
if (lval &lt; numeric_limits&lt;int&gt;::min())
{
  err |= ios_base::failbit;
  val = numeric_limits&lt;int&gt;::min();
}
else if (lval &gt; numeric_limits&lt;int&gt;::max())
{
  err |= ios_base::failbit;
  val = numeric_limits&lt;int&gt;::max();
}
else
  val = static_cast&lt;int&gt;(lval);
setstate(err);
</pre></blockquote>
</blockquote>

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


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



<p id="res-696"><b>Proposed resolution:</b></p>
<p>
Change 28.3.4.3.2.3 <a href="https://wg21.link/facet.num.get.virtuals">[facet.num.get.virtuals]</a>, p1:
</p>

<blockquote><p>
-1- <i>Effects:</i> Reads characters from <code>in</code>, interpreting them
according to <code>str.flags()</code>, <code>use_facet&lt;ctype&lt;charT&gt;
&gt;(loc)</code>, and <code>use_facet&lt; numpunct&lt;charT&gt;
&gt;(loc)</code>, where <code>loc</code> is <code>str.getloc()</code>. <del>If an error
occurs, <code>val</code> is unchanged; otherwise it is set to the resulting value.</del>
</p></blockquote>

<p>
Change 31.7.5.3.2 <a href="https://wg21.link/istream.formatted.arithmetic">[istream.formatted.arithmetic]</a>, p2 and p3:
</p>

<blockquote>
<pre>
operator>>(short&amp; val);
</pre>
<blockquote>
<p>
-2- The conversion occurs as if performed by the following code fragment (using the same notation as for 
the preceding code fragment):
</p>

<blockquote><pre>
typedef num_get&lt;charT,istreambuf_iterator&lt;charT,traits&gt; &gt; numget;
iostate err = ios<del>tate</del><ins>_base</ins>::goodbit;
long lval;
use_facet&lt;numget&gt;(loc).get(*this, 0, *this, err, lval);
<del>if (err != 0)
  ;
else if (lval &lt; numeric_limits&lt;short&gt;::min()
  || numeric_limits&lt;short&gt;::max() &lt; lval)
     err = ios_base::failbit;</del>
<ins>if (lval &lt; numeric_limits&lt;short&gt;::min())
{
  err |= ios_base::failbit;
  val = numeric_limits&lt;short&gt;::min();
}
else if (lval &gt; numeric_limits&lt;short&gt;::max())
{
  err |= ios_base::failbit;
  val = numeric_limits&lt;short&gt;::max();
}</ins>
else
  val = static_cast&lt;short&gt;(lval);
setstate(err);
</pre></blockquote>

</blockquote>

<pre>
operator>>(int&amp; val);
</pre>
<blockquote>
<p>
-3- The conversion occurs as if performed by the following code fragment (using the same notation as for 
the preceding code fragment):
</p>

<blockquote><pre>
typedef num_get&lt;charT,istreambuf_iterator&lt;charT,traits&gt; &gt; numget;
iostate err = ios<del>tate</del><ins>_base</ins>::goodbit;
long lval;
use_facet&lt;numget&gt;(loc).get(*this, 0, *this, err, lval);
<del>if (err != 0)
  ;
else if (lval &lt; numeric_limits&lt;int&gt;::min()
  || numeric_limits&lt;int&gt;::max() &lt; lval)
     err = ios_base::failbit;</del>
<ins>if (lval &lt; numeric_limits&lt;int&gt;::min())
{
  err |= ios_base::failbit;
  val = numeric_limits&lt;int&gt;::min();
}
else if (lval &gt; numeric_limits&lt;int&gt;::max())
{
  err |= ios_base::failbit;
  val = numeric_limits&lt;int&gt;::max();
}</ins>
else
  val = static_cast&lt;int&gt;(lval);
setstate(err);
</pre></blockquote>

</blockquote>

</blockquote>





</body>
</html>
