This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
3456. Pattern used bystd::from_chars
is underspecified
Section: 28.2.3 [charconv.from.chars] Status: New Submitter: Jonathan Wakely Opened: 2020-06-23 Last modified: 2020-09-06
Priority: 3
View other active issues in [charconv.from.chars].
View all other issues in [charconv.from.chars].
View all issues with New status.
Discussion:
The intention of 28.2.3 [charconv.from.chars] p7 is that the fmt
argument modifies the expected pattern, so that only a specific subset of valid strtod
patterns are recognized for each format. This is not clear from the wording.
fmt == chars_format::fixed
no exponent is to be used, so any trailing characters that match the form of a strtod
exponent are ignored. For example, "1.23e4"
should produce the result 1.23
for the fixed format. The current wording says "the optional exponent part shall not appear" which can be interpreted to mean that "1.23e4"
violates a precondition and so has undefined behaviour! When fmt != chars_format::hex
only decimal numbers should be recognized. This means that for any format except scientific, "0x123"
produces 0.0
(it's invalid when fmt == chars_format::scientific
because there's no exponent). The current wording only says that when hex
is used the string has an assumed "0x"
prefix, so is interpreted as a hexadecimal float, it doesn't say that when fmt != hex
that the string is not interpreted as a hexadecimal float. Two alternative resolutions are provided, one is a minimal fix and the other attempts to make it clearer by not referring to a modified version of the C rules.
[2020-07-14; Jonathan fixes the strtod
call in Option B]
[2020-07-17; Priority set to 3 in telecon]
Proposed resolution:
This wording is relative to N4861.
Option A:Modify 28.2.3 [charconv.from.chars] as indicated:
from_chars_result from_chars(const char* first, const char* last, float& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, double& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, long double& value, chars_format fmt = chars_format::general);-6- Preconditions:
-7- Effects: The pattern is the expected form of the subject sequence in the "C" locale, as described forfmt
has the value of one of the enumerators ofchars_format
.strtod
, except that
(7.1) — the sign
'+'
may only appear in the exponent part;(7.2) — if
fmt
haschars_format::scientific
set but notchars_format::fixed
, the otherwise optional exponent part shall appear exponent part is not optional;(7.3) — if
fmt
haschars_format::fixed
set but notchars_format::scientific
, the optional exponent part shall not appear; and there is no exponent part;(?.?) — if
fmt
is notchars_format::hex
, only decimal digits and an optional'.'
appear before the exponent part (if any); and(7.4) — if
fmt
ischars_format::hex
, the prefix"0x"
or"0X"
is assumed. [Example: The string0x123
is parsed to have the value0
with remaining charactersx123
. — end example]In any case, the resulting
value
is one of at most two floating-point values closest to the value of the string matching the pattern.
Modify 28.2.3 [charconv.from.chars] as indicated:
from_chars_result from_chars(const char* first, const char* last, float& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, double& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, long double& value, chars_format fmt = chars_format::general);-6- Preconditions:
-7- Effects: The pattern is the expected form of the subject sequence in the "C" locale, as described forfmt
has the value of one of the enumerators ofchars_format
.strtod
, except that The pattern is an optional'-'
sign followed by one of:
(7.1) — the sign
'+'
may only appear in the exponent partINF
orINFINITY
, ignoring case;(7.2) — if
fmt
haschars_format::scientific
set but notchars_format::fixed
, the otherwise optional exponent part shall appear ifnumeric_limits<T>::has_quiet_NaN
istrue
,NAN
orNAN(
n-char-sequenceopt)
, ignoring case in theNAN
part, where:n-char-sequence: digit nondigit n-char-sequence digit n-char-sequence nondigit;
(7.3) — if
fmt
haschars_format::fixed
set but notchars_format::scientific
, the optional exponent part shall not appear; and iffmt
is equal tochars_format::scientific
, a sequence of characters matching chars-format-dec exponent-part, where:chars-format-dec: fractional-constant digit-sequence;
(7.4) — if
fmt
ischars_format::hex
, the prefix"0x"
or"0X"
is assumed. [Example: The string0x123
is parsed to have the value0
with remaining charactersx123
. — end example] iffmt
is equal tochars_format::fixed
, a sequence of characters matching chars-format-dec;(?.?) — if
fmt
is equal tochars_format::general
, a sequence of characters matching chars-format-dec exponent-partopt; or(?.?) — if
fmt
is equal tochars_format::hex
, a sequence of characters matching chars-format-hex binary-exponent-partopt, where:chars-format-hex: hexadecimal-fractional-constant hexadecimal-digit-sequence[Note: The pattern is derived from the subject sequence in the
"C"
locale forstrtod
, with the value offmt
limiting which forms of the subject sequence are recognized, and with no0x
or0X
prefix recognized. — end note]For a character sequence
INF
,INFINITY
,NAN
, orNAN(
n-char-sequenceopt)
the resulting value is obtained as if by evaluatingstrtod(string(first, last).c_str(), nullptr)
in the"C"
locale. In all other cases In any case, the resultingvalue
is one of at most two floating-point values closest to the value of the string matching the pattern.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4