<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1169: num_get not fully compatible with strto*</title>
<meta property="og:title" content="Issue 1169: num_get not fully compatible with strto*">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1169.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++17">C++17</a> status.</em></p>
<h3 id="1169"><a href="lwg-defects.html#1169">1169</a>. <code>num_get</code> not fully compatible with <code>strto*</code></h3>
<p><b>Section:</b> 28.3.4.3.2.3 <a href="https://wg21.link/facet.num.get.virtuals">[facet.num.get.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Cosmin Truta <b>Opened:</b> 2009-07-04 <b>Last modified:</b> 2017-07-30</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="lwg-index-open.html#facet.num.get.virtuals">active issues</a> in [facet.num.get.virtuals].</p>
<p><b>View all other</b> <a href="lwg-index.html#facet.num.get.virtuals">issues</a> in [facet.num.get.virtuals].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>
<p>
As specified in the latest draft,
<a 
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2914.pdf">N2914</a>,
<code>num_get</code> is still not fully compatible with the following C
functions: <code>strtoul</code>, <code>strtoull</code>, 
<code>strtof</code> and
<code>strtod</code>.
</p>
<p>
In C, when conversion of a string to an unsigned integer type falls 
outside the
representable range, <code>strtoul</code> and <code>strtoull</code> return
<code>ULONG_MAX</code> and <code>ULLONG_MAX</code>, respectively, 
regardless
whether the input field represents a positive or a negative value.
On the other hand, the result of <code>num_get</code> conversion of 
negative
values to unsigned integer types is zero. This raises a compatibility 
issue.
</p>
<p>
Moreover, in C, when conversion of a string to a floating-point type falls
outside the representable range, <code>strtof</code>, <code>strtod</code> 
and
<code>strtold</code> return <code>&plusmn;HUGE_VALF</code>,
<code>&plusmn;HUGE_VAL</code> and <code>&plusmn;HUGE_VALL</code>, respectively.
On the other hand, the result of <code>num_get</code> conversion of such
out-of-range floating-point values results in the most positive/negative
representable value.
Although many C library implementations do implement <code>HUGE_VAL</code>
(etc.) as the highest representable (which is, usually, the infinity), 
this isn't required by the C standard. The C library specification makes no
statement regarding the value of <code>HUGE_VAL</code> and friends, which
potentially raises the same compatibility issue as in the above case of
unsigned integers.
In addition, neither C nor C++ define symbolic constants for the maximum
representable floating-point values (they only do so only for the maximum
representable <i>finite</i> floating-point values), which raises a 
usability
issue (it would be hard for the programmer to check the result of
<code>num_get</code> against overflow).
</p>
<p>
As such, we propose to adjust the specification of <code>num_get</code> to
closely follow the behavior of all of its underlying C functions.
</p>



<p><i>[
2010 Rapperswil:
]</i></p>


<blockquote><p>
Some concern that this is changing the specification for an existing C++03 function, but it was 
pointed out that this was underspecified as resolved by issue 23.  This is clean-up for that 
issue in turn. Some concern that we are trying to solve the same problem in both clause 22 and 27.
</p>
<p>
Bill: There's a change here as to whether val is stored to in an error case.
</p>
<p>
Pablo: Don't think this changes whether val is stored to or not, but changes the value that is stored.
</p>
<p>
Bill: Remembers having skirmishes with customers and testers as to whether val is stored to, and the resolution was not to store in error cases.
</p>
<p>
Howard: Believes since C++03 we made a change to always store in overflow.
</p>
<p>
Everyone took some time to review the issue.
</p>
<p>
Pablo: C++98 definitely did not store any value during an error condition.
</p>
<p>
Dietmar: Depends on the question of what is considered an error, and whether overflow is an error or not, which was the crux of LWG 23.
</p>
<p>
Pablo: Yes, but given the "zero, if the conversion function fails to convert the entire field", we are requiring every error condition to store.
</p>
<p>
Bill: When did this happen?
</p>
<p>
Alisdair: One of the last two or three meetings.
</p>
<p>
Dietmar: To store a value in case of failure is a very bad idea.
</p>
<p>
Move to Open, needs more study.
</p>
</blockquote>

<p><i>[2011-03-24 Madrid meeting]</i></p>


<p>Move to deferred</p>

<p><i>[
2011 Bloomington
]</i></p>


<p>
The proposed wording looks good, no-one sure why this was held back before.  Move to Review.
</p>


<p><i>[2012,Kona]</i></p>

<p>
Move to Open.
</p>
<p>
THe issues is what to do with <code>-1</code>.  Should it match 'C' or do the "sane" thing.
A fix here changes behavior, but is probably what we want.
</p>
<p>
Pablo to provide wording, with help from Howard.
</p>

<p><i>[2015-05-06 Lenexa: Move to Ready]</i></p>

<p>STL: I like that this uses strtof, which I think is new in C99. that avoids truncation from using atof. I have another issue ...</p>
<p>MC: yes LWG 2403 (stof should call strtof)</p>
<p>PJP: the last line is horrible, you don't assign to err, you call setstate(ios_base::failbit). Ah, no, this is inside num_get so the caller does the setstate.</p>
<p>MC: we need all these words. are they the right words?</p>
<p>JW: I'd like to take a minute to check my impl. Technically this implies a change in behaviour (from always using strtold and checking the extracted floating point value, to using the right function). Oh, we already do exactly this.</p>
<p>MC: Move to Ready</p>
<p>6 in favor, none opposed, 1 abstention</p>


<p id="res-1169"><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> as follows:
</p>
<blockquote>
<p>
<b>Stage 3:</b>
The sequence of <code>char</code>s accumulated in stage 2 (the field) is
converted to a numeric value by the rules of one of the functions declared in
the header <code>&lt;cstdlib&gt;</code>:
</p>
<ul>
<li>For a signed integer value, the function <code>strtoll</code>.</li>
<li>For an unsigned integer value, the function <code>strtoull</code>.</li>
<li><ins>For a <code>float</code> value, the function
    <code>strtof</code>.</ins></li>
<li><ins>For a <code>double</code> value, the function
    <code>strtod</code>.</ins></li>
<li>For a <del>floating-point</del> <ins><code>long double</code></ins>
    value, the function <code>strtold</code>.</li>
</ul>
<p>
The numeric value to be stored can be one of:
</p>
<ul>
<li>zero, if the conversion function fails to convert the entire field.
    <del><code>ios_base::failbit</code> is assigned to <code>err</code>.</del></li>
<li>the most positive <ins>(or negative)</ins> representable value, if
    the field <ins>to be converted to a signed integer type</ins> represents a
    value too large positive <ins>(or negative)</ins> to be represented in
    <code>val</code>.
    <del><code>ios_base::failbit</code> is assigned to <code>err</code>.</del></li>
<li><del>the most negative representable value or zero for an unsigned integer
    type, if the field represents a value too large negative to be represented
    in <code>val</code>.
    <code>ios_base::failbit</code> is assigned to <code>err</code>.</del></li>
<li><ins>the most positive representable value, if the field to be converted to
    an unsigned integer type represents a value that cannot be represented in
    <code>val</code>.</ins></li>
<li>the converted value, otherwise.</li>
</ul>
<p>
The resultant numeric value is stored in <code>val</code>.
<ins>If the conversion function fails to convert the entire field, or if the
field represents a value outside the range of representable values,
<code>ios_base::failbit</code> is assigned to <code>err</code>.</ins>
</p>
</blockquote>






</body>
</html>
