This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.
Section: 184.108.40.206.2 [facet.num.get.virtuals] Status: NAD Submitter: Cosmin Truta Opened: 2007-04-05 Last modified: 2016-02-10
Priority: Not Prioritized
View all other issues in [facet.num.get.virtuals].
View all issues with NAD status.
From Section 220.127.116.11.2 [facet.num.get.virtuals], paragraphs 11 and 12, it is implied
that the value read from a stream must be stored
even if the placement of thousands separators does not conform to the
grouping() specification from the
Since incorrectly-placed thousands separators are flagged as an extraction
failure (by the means of
failbit), we believe it is better not
to store the value. A consistent strategy, in which any kind of extraction
failure leaves the input item intact, is conceptually cleaner, is able to avoid
corner-case traps, and is also more understandable from the programmer's point
Here is a quote from "The C++ Programming Language (Special Edition)" by B. Stroustrup (Section D.4.2.3, pg. 897):
"If a value of the desired type could not be read, failbit is set in r. [...] An input operator will use r to determine how to set the state of its stream. If no error was encountered, the value read is assigned through v; otherwise, v is left unchanged."
This statement implies that
rdstate() alone is sufficient to
determine whether an extracted value is to be assigned to the input item
val passed to
do_get. However, this is in disagreement
with the current C++ Standard. The above-mentioned assumption is true in all
cases, except when there are mismatches in digit grouping. In the latter case,
the parsed value is assigned to val, and, at the same time, err
is assigned to
ios_base::failbit (essentially "lying" about the
success of the operation). Is this intentional? The current behavior raises
both consistency and usability concerns.
Although digit grouping is outside the scope of
scanf (on which
the virtual methods of
num_get are based), handling of grouping
should be consistent with the overall behavior of scanf. The specification of
scanf makes a distinction between input failures and matching
failures, and yet both kinds of failures have no effect on the input items
scanf. A mismatch in digit grouping logically falls in
the category of matching failures, and it would be more consistent, and less
surprising to the user, to leave the input item intact whenever a failure is
The extraction of
bool is another example outside the scope of
scanf, and yet consistent, even in the event of a successful
extraction of a
long but a failed conversion from
Inconsistency is further aggravated by the fact that, when failbit is set,
subsequent extraction operations are no-ops until
explicitly cleared. Assuming that there is no explicit handling of
rdstate() (as in
cin>>i>>j) it is
counter-intuitive to be able to extract an integer with mismatched digit
grouping, but to be unable to extract another, properly-formatted integer
that immediately follows.
failbit, and selectively assigning a value to
the input item, raises usability problems. Either the strategy of
scanf (when there is no extracted value in case of failure), or
the strategy of the
strtol family (when there is always an
extracted value, and there are well-defined defaults in case of a failure) are
easy to understand and easy to use. On the other hand, if
alone cannot consistently make a difference between a failed extraction, and a
successful but not-quite-correct extraction whose output happens to be the same
as the previous value, the programmer must resort to implementation tricks.
Consider the following example:
int i = old_i; cin >> i; if (cin.fail()) // can the value of i be trusted? // what does it mean if i == old_i? // ...
Last but not least, the current behvaior is not only confusing to the casual
reader, but it has also been confusing to some book authors. Besides
Stroustrup's book, other books (e.g. "Standard C++ IOStreams and Locales" by
Langer and Kreft) are describing the same mistaken assumption. Although books
are not to be used instead of the standard reference, the readers of these
books, as well as the people who are generally familiar to
are even more likely to misinterpret the standard, and expect the input items
to remain intact when a failure occurs.
Change 18.104.22.168.2 [facet.num.get.virtuals]:
Stage 3: The result of stage 2 processing can be one of
- A sequence of
charshas been accumulated in stage 2 that is converted (according to the rules of
scanf) to a value of the type of
This value is stored in
ios_base::goodbitis stored in
- The sequence of
charsaccumulated in stage 2 would have caused
scanfto report an input failure.
ios_base::failbitis assigned to
Digit grouping is checked. That is, the positions of discarded separators is examined for consistency with
use_facet<numpunct<charT> >(loc).grouping(). If they are not consistent then
ios_base::failbitis assigned to
post-Toronto: Changed from New to NAD at the request of the author. The preferred solution of N2327 makes this resolution obsolete.