Section: 28.3.4.3.2.3 [facet.num.get.virtuals] Status: C++11 Submitter: Martin Sebor Opened: 2003-09-18 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [facet.num.get.virtuals].
View all other issues in [facet.num.get.virtuals].
View all issues with C++11 status.
Discussion:
The requirements specified in Stage 2 and reiterated in the rationale of DR 221 (and echoed again in DR 303) specify that num_get<charT>:: do_get() compares characters on the stream against the widened elements of "012...abc...ABCX+-"
An implementation is required to allow programs to instantiate the num_get template on any charT that satisfies the requirements on a user-defined character type. These requirements do not include the ability of the character type to be equality comparable (the char_traits template must be used to perform tests for equality). Hence, the num_get template cannot be implemented to support any arbitrary character type. The num_get template must either make the assumption that the character type is equality-comparable (as some popular implementations do), or it may use char_traits<charT> to do the comparisons (some other popular implementations do that). This diversity of approaches makes it difficult to write portable programs that attempt to instantiate the num_get template on user-defined types.
[Kona: the heart of the problem is that we're theoretically
supposed to use traits classes for all fundamental character
operations like assignment and comparison, but facets don't have
traits parameters. This is a fundamental design flaw and it
appears all over the place, not just in this one place. It's not
clear what the correct solution is, but a thorough review of facets
and traits is in order. The LWG considered and rejected the
possibility of changing numeric facets to use narrowing instead of
widening. This may be a good idea for other reasons (see issue
459), but it doesn't solve the problem raised by this
issue. Whether we use widen or narrow the num_get
facet
still has no idea which traits class the user wants to use for
the comparison, because only streams, not facets, are passed traits
classes. The standard does not require that two different
traits classes with the same char_type
must necessarily
have the same behavior.]
Informally, one possibility: require that some of the basic
character operations, such as eq
, lt
,
and assign
, must behave the same way for all traits classes
with the same char_type
. If we accept that limitation on
traits classes, then the facet could reasonably be required to
use char_traits<charT>
.
[ 2009-07 Frankfurt ]
There was general agreement that the standard only needs to specify the behavior when the character type is char or wchar_t.
Beman: we don't need to worry about C++1x because there is a non-zero possibility that we would have a replacement facility for iostreams that would solve these problems.
We need to change the following sentence in [locale.category], paragraph 6 to specify that C is char and wchar_t:
"A template formal parameter with name C represents the set of all possible specializations on a parameter that satisfies the requirements for a character on which any member of the iostream components can be instantiated."
We also need to specify in 27 that the basic character operations, such as eq, lt, and assign use std::char_traits.
Daniel volunteered to provide wording.
[ 2009-09-19 Daniel provided wording. ]
[ 2009-10 Santa Cruz: ]
Leave as Open. Alisdair and/or Tom will provide wording based on discussions. We want to clearly state that streams and locales work just on
char
andwchar_t
(except where otherwise specified).
[ 2010-02-06 Tom updated the proposed wording. ]
[ The original proposed wording is preserved here: ]
Change 28.3.3.1.2.1 [locale.category]/6:
[..] A template formal parameter with name
C
represents the set of all possible specializations on achar
orwchar_t
parameterthat satisfies the requirements for a character on which any of the iostream components can be instantiated. [..]Add the following sentence to the end of 28.3.4.3 [category.numeric]/2:
[..] These specializations refer to [..], and also for the
ctype<>
facet to perform character classification. Implementations are encouraged but not required to use thechar_traits<charT>
functions for all comparisons and assignments of characters of typecharT
that do not belong to the set of required specializations.Change 28.3.4.3.2.3 [facet.num.get.virtuals]/3:
Stage 2: If
in==end
then stage 2 terminates. Otherwise acharT
is taken fromin
and local variables are initialized as if bychar_type ct = *in; using tr = char_traits<char_type>; const char_type* pos = tr::find(atoms, sizeof(src) - 1, ct); char c = src[find(atoms, atoms + sizeof(src) - 1, ct) - atomspos ? pos - atoms : sizeof(src) - 1]; if (tr::eq(ct,ct ==use_facet<numpunct<charT>(loc).decimal_point())) c = '.'; bool discard = tr::eq(ct,ct ==use_facet<numpunct<charT>(loc).thousands_sep()) && use_facet<numpunct<charT> >(loc).grouping().length() != 0;where the values
src
andatoms
are defined as if by: [..][Remark of the author: I considered to replace the initialization "
char_type ct = *in;
" by the sequence "char_type ct; tr::assign(ct, *in);
", but decided against it, because it is a copy-initialization context, not an assignment]Add the following sentence to the end of 28.3.4.6 [category.time]/1:
[..] Their members use [..] , to determine formatting details. Implementations are encouraged but not required to use the
char_traits<charT>
functions for all comparisons and assignments of characters of typecharT
that do not belong to the set of required specializations.Change 28.3.4.6.2.2 [locale.time.get.members]/8 bullet 4:
The next element ofFor the next elementfmt
is equal to'%'
c
offmt char_traits<char_type>::eq(c, use_facet<ctype<char_type>>(f.getloc()).widen('%')) == true
, [..]Add the following sentence to the end of 28.3.4.7 [category.monetary]/2:
Their members use [..] to determine formatting details. Implementations are encouraged but not required to use the
char_traits<charT>
functions for all comparisons and assignments of characters of typecharT
that do not belong to the set of required specializations.Change 28.3.4.7.2.3 [locale.money.get.virtuals]/4:
[..] The value
units
is produced as if by:for (int i = 0; i < n; ++i) buf2[i] = src[char_traits<charT>::find(atoms,atoms+sizeof(src), buf1[i]) - atoms]; buf2[n] = 0; sscanf(buf2, "%Lf", &units);Change 28.3.4.7.3.3 [locale.money.put.virtuals]/1:
[..] for character buffers
buf1
andbuf2
. If for the first characterc
indigits
orbuf2
is equal toct.widen('-')
char_traits<charT>::eq(c, ct.widen('-')) == true
, [..]Add a footnote to the first sentence of 31.7.5.3.2 [istream.formatted.arithmetic]/1:
As in the case of the inserters, these extractors depend on the locale's
num_get<>
(22.4.2.1) object to perform parsing the input stream data.(footnote) [..]footnote) If the traits of the input stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.Add a footnote to the second sentence of 31.7.6.3.2 [ostream.inserters.arithmetic]/1:
Effects: The classes
num_get<>
andnum_put<>
handle locale-dependent numeric formatting and parsing. These inserter functions use the imbued locale value to perform numeric formatting.(footnote) [..]footnote) If the traits of the output stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.Add a footnote after the first sentence of 31.7.8 [ext.manip]/4:
Returns: An object of unspecified type such that if in is an object of type
basic_istream<charT, traits>
then the expressionin >> get_money(mon, intl)
behaves as if it calledf(in, mon, intl)
, where the functionf
is defined as:(footnote) [..]footnote) If the traits of the input stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.Add a footnote after the first sentence of 31.7.8 [ext.manip]/5:
Returns: An object of unspecified type such that if
out
is an object of typebasic_ostream<charT, traits>
then the expressionout << put_money(mon, intl)
behaves as a formatted input function that callsf(out, mon, intl)
, where the functionf
is defined as:(footnote) [..]footnote) If the traits of the output stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.13) Add a footnote after the first sentence of 31.7.8 [ext.manip]/8:
Returns: An object of unspecified type such that if
in
is an object of type basic_istream<charT, traits>
then the expressionin >>get_time(tmb, fmt)
behaves as if it calledf(in, tmb, fmt)
, where the functionf
is defined as:(footnote) [..]footnote) If the traits of the input stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.Add a footnote after the first sentence of 31.7.8 [ext.manip]/10:
Returns: An object of unspecified type such that if
out
is an object of typebasic_ostream<charT, traits>
then the expressionout <<put_time(tmb, fmt)
behaves as if it calledf(out, tmb, fmt)
, where the functionf
is defined as:(footnote) [..]footnote) If the traits of the output stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.
[ 2010 Pittsburgh: ]
Moved to Ready with only two of the bullets. The original wording is preserved here:
Change 28.3.3.1.2.1 [locale.category]/6:
[..] A template formal parameter with name
C
represents the setof all possible specializations on aof types containingchar
,wchar_t
, and any other implementation-defined character typeparameterthat satisfies the requirements for a character on which any of the iostream components can be instantiated. [..]Add the following sentence to the end of 28.3.4.3 [category.numeric]/2:
[..] These specializations refer to [..], and also for the
ctype<>
facet to perform character classification. [Note: Implementations are encouraged but not required to use thechar_traits<charT>
functions for all comparisons and assignments of characters of typecharT
that do not belong to the set of required specializations - end note].Change 28.3.4.3.2.3 [facet.num.get.virtuals]/3:
Stage 2: If
in==end
then stage 2 terminates. Otherwise acharT
is taken fromin
and local variables are initialized as if bychar_type ct = *in; using tr = char_traits<char_type>; const char_type* pos = tr::find(atoms, sizeof(src) - 1, ct); char c = src[find(atoms, atoms + sizeof(src) - 1, ct) - atomspos ? pos - atoms : sizeof(src) - 1]; if (tr::eq(ct,ct ==use_facet<numpunct<charT>(loc).decimal_point())) c = '.'; bool discard = tr::eq(ct,ct ==use_facet<numpunct<charT>(loc).thousands_sep()) && use_facet<numpunct<charT> >(loc).grouping().length() != 0;where the values
src
andatoms
are defined as if by: [..][Remark of the author: I considered to replace the initialization "
char_type ct = *in;
" by the sequence "char_type ct; tr::assign(ct, *in);
", but decided against it, because it is a copy-initialization context, not an assignment]Add the following sentence to the end of 28.3.4.6 [category.time]/1:
[..] Their members use [..] , to determine formatting details. [Note: Implementations are encouraged but not required to use the
char_traits<charT>
functions for all comparisons and assignments of characters of typecharT
that do not belong to the set of required specializations - end note].Change 28.3.4.6.2.2 [locale.time.get.members]/8 bullet 4:
The next element ofFor the next elementfmt
is equal to'%'
c
offmt char_traits<char_type>::eq(c, use_facet<ctype<char_type>>(f.getloc()).widen('%')) == true
, [..]Add the following sentence to the end of 28.3.4.7 [category.monetary]/2:
Their members use [..] to determine formatting details. [Note: Implementations are encouraged but not required to use the
char_traits<charT>
functions for all comparisons and assignments of characters of typecharT
that do not belong to the set of required specializations - end note].Change 28.3.4.7.2.3 [locale.money.get.virtuals]/4:
[..] The value
units
is produced as if by:for (int i = 0; i < n; ++i) buf2[i] = src[char_traits<charT>::find(atoms,atoms+sizeof(src), buf1[i]) - atoms]; buf2[n] = 0; sscanf(buf2, "%Lf", &units);Change 28.3.4.7.3.3 [locale.money.put.virtuals]/1:
[..] for character buffers
buf1
andbuf2
. If for the first characterc
indigits
orbuf2
is equal toct.widen('-')
char_traits<charT>::eq(c, ct.widen('-')) == true
, [..]Add a new paragraph after the first paragraph of 31.2.3 [iostreams.limits.pos]/1:
In the classes of clause 27, a template formal parameter with name
charT
represents one of the set of types containingchar
,wchar_t
, and any other implementation-defined character type that satisfies the requirements for a character on which any of the iostream components can be instantiated.Add a footnote to the first sentence of 31.7.5.3.2 [istream.formatted.arithmetic]/1:
As in the case of the inserters, these extractors depend on the locale's
num_get<>
(22.4.2.1) object to perform parsing the input stream data.(footnote) [..]footnote) If the traits of the input stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.Add a footnote to the second sentence of 31.7.6.3.2 [ostream.inserters.arithmetic]/1:
Effects: The classes
num_get<>
andnum_put<>
handle locale-dependent numeric formatting and parsing. These inserter functions use the imbued locale value to perform numeric formatting.(footnote) [..]footnote) If the traits of the output stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.Add a footnote after the first sentence of 31.7.8 [ext.manip]/4:
Returns: An object of unspecified type such that if in is an object of type
basic_istream<charT, traits>
then the expressionin >> get_money(mon, intl)
behaves as if it calledf(in, mon, intl)
, where the functionf
is defined as:(footnote) [..]footnote) If the traits of the input stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.Add a footnote after the first sentence of 31.7.8 [ext.manip]/5:
Returns: An object of unspecified type such that if
out
is an object of typebasic_ostream<charT, traits>
then the expressionout << put_money(mon, intl)
behaves as a formatted input function that callsf(out, mon, intl)
, where the functionf
is defined as:(footnote) [..]footnote) If the traits of the output stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.Add a footnote after the first sentence of 31.7.8 [ext.manip]/8:
Returns: An object of unspecified type such that if
in
is an object of type basic_istream<charT, traits>
then the expressionin >>get_time(tmb, fmt)
behaves as if it calledf(in, tmb, fmt)
, where the functionf
is defined as:(footnote) [..]footnote) If the traits of the input stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.Add a footnote after the first sentence of 31.7.8 [ext.manip]/10:
Returns: An object of unspecified type such that if
out
is an object of typebasic_ostream<charT, traits>
then the expressionout <<put_time(tmb, fmt)
behaves as if it calledf(out, tmb, fmt)
, where the functionf
is defined as:(footnote) [..]footnote) If the traits of the output stream has different semantics for
lt()
,eq()
, andassign()
thanchar_traits<char_type>
, this may give surprising results.
Proposed resolution:
Change 28.3.3.1.2.1 [locale.category]/6:
[..] A template formal parameter with name
C
represents the setof all possible specializations on aof types containingchar
,wchar_t
, and any other implementation-defined character typeparameterthat satisfies the requirements for a character on which any of the iostream components can be instantiated. [..]
Add a new paragraph after the first paragraph of 31.2.3 [iostreams.limits.pos]/1:
In the classes of clause 27, a template formal parameter with name
charT
represents one of the set of types containingchar
,wchar_t
, and any other implementation-defined character type that satisfies the requirements for a character on which any of the iostream components can be instantiated.