ISO/ IEC JTC1/SC22/WG21 N0788

                                         Doc. No.:   WG21/N0788=X3J16/95-0188
                                         Date:       26 Sep 1995
                                         Project:    C++ Standard Library
                                         Reply to:   Nathan Myers
                                                     <myersn@roguewave.com>
 
        Clause 22 (Locale) Issues (Revision 2)
 
** Revision History:
 
   Revision 0 - 22 May 1995 [was Version 1]
   Revision 1 - 09 Jul 1995 [was Version 2] (Edits before Monterey)
   Revision 2 - 26 Sep 1995 (Pre-Tokyo)
 
** Introduction
 
This document is a summary of issues identified for the Clause 22,
identifying resolutions as they are voted on and recommendations
for unsolved problems in the Draft.
 
--------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-004
** Title:          Description of _byname facets too vague
** Sections:       [lib.locale.facet]
** Status:         active
 
** Description:
Paragraph 4, where _byname<> classes are described, leaves some
(unspecified) issues unresolved.
 
** Discussion:
The following was added to paragraph 4:
"If the const char* argument to a _byname facet constructor does not
identify a valid locale name, the constructor throws an exception of
type std::runtime_error."
 
[Plauger has remarked that other matters remain unspecified.  I am
hoping he will offer details in time to discuss resolutions.]
 
** Proposed Resolution:
 
** Requestor: P.J. Plauger
** Owner:
 
--------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-009
** Title:          Global locale effect on C Lib functions unspecified
** Sections:       [lib.locale.statics]
** Status:         active
 
** Description:
The global locale locale(), as set by locale::global(...), is described
as affecting the C library functions, but the Draft doesn't say what
facets and members are used.
 
** Discussion:
In principle, the C library functions could be implemented in
terms of global locale facets; however, specifying what facets
they use, and how, would require a long, detailed proposal.
Worse, the common use of macros in the C library to implement
(e.g.) isupper() means that maintaining link compatibility with
C code could be impossible in some environments.
 
Instead, the proposal is to relax the required coupling between
the C++ and C libraries.
 
** Proposed Resolution:
Specify locale::global as follows:
 
  static locale locale::global(const locale& loc);
 
  Effects: Causes future calls to the constructor locale() to return a
   copy of loc.  If loc has a name, does
      std::setlocale(LC_ALL, loc.name().c_str()).
   If loc is unnamed, the effect on the C locale, if any, is
   implementation-defined.  If loc is (a copy of) the value returned
   by locale::transparent(), throws runtime_error.
  Returns: the previous value of locale().
 
And the constructor locale():
 
  locale() throw();
 
  Default constructor; a snapshot of the current global locale.
  Effects: Constructs a copy of the argument last passed to
   locale::global(const locale&). If locale::global() has not
   been called, resulting facets have virtual function semantics
   identical to those of locale("C").
  Note: It is implementation-defined whether a call to the C
   library function setlocale(category, name) (1) affects this
   constructor identically as a call to
     locale::global(locale(locale(), name, category)),
   or (2) has no effect on it.
 
** Requestor:     P. J. Plauger
** Owner:         Nathan Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-016
** Title:          Numeric parsing & formatting description is poorly organized
** Sections:       22 (many)
** Status:         active
 
** Description:
As several people have pointed out, the descriptions of parsing and
formatting semantics for iostreams, and facet members put* and get*,
are scattered in both Clauses 22 and 27.  Further, they reference C
Library semantics in ways that are incompatible with the C++ Library
environment.
 
** Discussion:
Since iostreams delegates all its formatting and parsing to locale,
the descriptions of such semantics might best be in Clause 22.  Also,
the more general semantics of locale facilities raises some questions
about parsing: e.g. what is the effect if a digit group separator is
specified to be a digit value, or equal to the decimal separator?
(Plauger)
 
** Proposed Resolution:
Encourage editoral aggressiveness in consolidating the descriptions
of parsing and formatting, and in collecting issues that arise.
 
See also issue 22-050.
 
** Requestor:
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-017
** Title:          facet members put*() have no way to detect output errors.
** Sections:       [lib.ostream.formatted.reqmts], paragraph 3
** Status:         active
 
** Description:
Facet members take a single Output Iterator and assign characters
through it.  This interface offers no indication of failure, and no
way to limit the number of characters produced.
 
** Discussion:
ostream operators << are required to report output errors, but
the put() members give no indication of errors because the Output
Iterator interface used by the put() members offers no indication
of failure.  However, an iterator that fails can record the fact.
 
The ostreambuf_iterator<> that ostream passes to the put() members
can be extended to provide the necessary semantics.
 
** Proposed Resolution:
Add to ostreambuf_iterator the following member:
 
  bool failed() const throw();
 
  Returns: false if no previous call to streambuf::sputc reported
   a failure, true otherwise.
 
Add to [lib.ostream.formatted.reqmts], paragraph 3:
 
  Checks for a failure by calling ostreambuf_iterator<>::failed(),
  and calls setstate(failbit) if true.
 
The example in the same section should be replaced with either:
 
  { sentry cerberos(*this); if (!cerberos) return;
    iostate save = exceptions(); exceptions(0);
    try {
      if (use_facet< num_put<charT,ostreambuf_iterator<charT,traits> >(
            getloc()).put(*this,*this,fill(),getloc(),val).failed())
        setstate(failbit); // won't throw
    } catch (...) { exceptions(save); setstate(badbit); throw; }
    exceptions(save);
    setstate(rdstate());  // might throw
  }
 
if the ostream::sentry proposal passes, or
 
  if (opfx()) {
    iostate save = exceptions(); exceptions(0);
    try {
      if (use_facet< num_put<charT,ostreambuf_iterator<charT,traits> >(
            getloc()).put(*this,*this,fill(),getloc(),val).failed())
        setstate(failbit);  // won't throw
    } catch (...) {
      setstate(badbit);  // won't throw
      exceptions(save);
      osfx();
      setstate(rdstate());  // might throw failure
      throw;
    }
    exceptions(save);
    osfx();
    setstate(rdstate());  // might throw failure
  }
 
if it doesn't.
 
** Note:
 
The complexity of these code snippets reveals the complexity of the
specification on how iostreams handle exceptions.  Probably we should
simplify it.  I recommend that a throw of ios_base::failure be propagated
without affecting the iostate.  Then the example above looks like:
 
  { sentry cerberos(*this); if (!cerberos) return;
    try {
      if (use_facet< num_put<charT,ostreambuf_iterator<charT,traits> >(
            getloc()).put(*this,*this,fill(),getloc(),val).failed())
        setstate(failbit);  // might throw
    }
    catch (const ios_base::failure&) { throw; }
    catch (...)                      { setstate(badbit); throw; }
  }
 
** Requestor:  Plauger
** Owner:      Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-018
** Title:          Hexadecimal and octal numeric parsing not specified
** Sections:       22
** Status:         active
 
** Description:
>From Box 24:
:  Is  support for syntax like "0xFF" required for iostreams support?  If
:  so, we need to add language describing it.
 
** Discussion:
AT&T iostreams did not support it on input, and generated it on output
if showbase was set.  Other implementations more closely matched C
printf/scanf conventions.  This may be an iostreams issue.
 
** Proposed Resolution:
Match whatever resolution of this issue is approved for iostreams.
 
** Requestor:
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-019
** Title:          numpunct<>::do_grouping not like C
** Sections:       22.2.3.1.1 [lib.facet.numpunct.members]
** Status:         active
 
** Description:
The result of numpunct<>::do_grouping() is a vector with semantics
somewhat similar to those of the C Library lconv::grouping char*
member.  It has been suggested they should be identical.
 
** Discussion:
It makes little difference what the form of the grouping objects is.
Matching the C interface makes integration of some code easier.
 
** Proposed Resolution:
Change the result type of numpunct<> and moneypunct<> members
grouping and do_grouping to basic_string<char> [not <charT>], and
specify that the contents returned by member c_str() are interpreted
identically as the C library struct member lconv::grouping.
 
** Requestor:      P.J. Plauger
** Owner:          Nathan Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-022
** Title:          time_get<>::get_* error semantics incomplete
** Sections:       22.2.5.1.2 [lib.locale.time.get.virtuals]
** Status:         active
 
** Description:
The descriptions of time_get<>::do_get_date and do_get_time don't say
how many characters are consumed if a recognizable date format is not
available.
 
** Discussion:
It was intended that these functions not be as rigorously defined
as the monetary and numeric parsers, to allow implementors more
latitude in recognizing the many variations in notation.
 
No limitation on the number of characters consumed, short of
end-of-sequence, seems universal enough.  There seems little
need for anything more restrictive anyway.
 
** Proposed Resolution:
Change the descriptions of time_get<>::do_get_date and do_get_time
"Returns:" sections to:
 
  Returns: An iterator pointing immediately beyond the last character
   recognized as possibly a part of the a valid [time|date].
 
** Requestor:
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-030
** Title:          Do facet gets/puts throw on error?
** Sections:       22 (many)
** Status:         active
 
** Description:
When a facet member get identifies an error, it is documented as
setting a bit in its "ios_type" argument's iostate.  In iostream,
when this happens an exception is thrown if the corresponding bit
is set in the exception state.  Does an exception get thrown under
the same circumstances in locale functions?  The Draft is inconsistent.
 
** Discussion:
If the locale doesn't throw, istream must check the error state
itself and throw; if locale throws, iostream probably needs to catch
and rethrow.  Thus, we have a choice:
 
1. Locale members throw if the exception bit says so.
2. Locale members don't throw, the only set iostate.
 
(1) implies that it is sufficient for the facet to call
setstate(failbit), which is the status quo.  This implies
that when istream calls these members, it must turn off
the exception control bits, and restore them after the member
returns.  At the same time, it must catch any exceptions
thrown.
 
** Proposed Resolution:
No change.  This implies that throwing behavior is controlled
by ios_base::exception() state.
 
** Requestor:
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-034
** Title:          locale::transparent restrictions gall
** Sections:       22.1.1
** Status:         active
 
** Description:
Plauger says:
  Paragraph 8 says that locale::transparent() has unspecified behavior
  when imbued on a stream or installed as the global locale. There is
  no good reason why this should be so and several reasons why the
  behavior should be clearly defined. The sentence should be struck.
 
and later:
  Paragraph 9 says that ``caching results from calls to locale facet
  member functions during calls to iostream inserters and extractors,
  and in streambufs between calls to basic_streambuf::imbue, is
  explicitly supported.'' In the case of inserters and extractors,
  this behavior follows directly from paragraph 8. No need to say it
  again. For basic_streambuf, the draft can (and should) say explicitly
  that the stream buffer fixates on a facet at imbue time and ignores
  any subsequent changes that might occur in the delivered facet
  until the next imbue time (if then). (An adequate lifetime for the
  facet can be assured by having the basic_streambuf object memorize
  a copy of a locale object directly containing the facet,
  as well as a pointer to the facet, for greater lookup speed.)
  In any event, saying something ``is explicitly supported'' doesn't
  make the behavior *required.* The paragraph should be struck, and
  words added to the description of basic_streambuf to clarify the
  lifetime of an imbued codecvt facet. (More words are needed here
  anyway, for other reasons.)
 
** Discussion
Editorial clarification is clearly needed.  The disputed semantics,
curiously, were originally recommended and justified by Tom Plum.
 
If a streambuf made a copy of an imbued transparent locale, it
would be fixated on nothing -- any change of the global locale
could eliminate the facets it refers to.  If it constructs a new
locale object to keep the facet, it is the same as if the current
global locale was imbued.
 
** Proposed Resolution:
Editorial.
 
** Requestor:      Plauger
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-035
** Title:          why no codecvt<char,char,mbstate_t>?
** Sections:       22.1.1.1.1 [lib.locale.category]
** Status:         active
 
** Description:
Plauger says:
  Table 46 lists the ctype facets codecvt<char, wchar_t, mbstate_t>
  and codecvt<wchar_t, char, mbstate_t> as being essential, but what
  about codecvt<char, char, mbstate_t>? Should say that this facet
  must be present and must cause no conversion.
 
** Discussion:
It would be equally reasonable to specify either of:
 
 - filebuf<char>::overflow and filebuf<char>::underflow
   use specialization to avoid needing to use
   codecvt<char,char,mbstate_t>, or
 
 - the category locale::ctype includes a facet of type
   codecvt<char,char,mbstate_t> specified to perform
   no conversion.
 
The former would result in cleaner object code; the latter is
easier to specify.
 
** Proposed Resolution:
Add to the locale::ctype category table entry in [lib.locale.category]
the required facet codecvt<char,char,mbstate_t>.  Specify below that
its member convert always returns codecvt_base::noconv.
 
** Requestor:      Plauger
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-037
** Title:          locale immutability disputed
** Sections:       22.1.1.3 [lib.locale.cons], [lib.locale.globals]
** Status:         active
 
** Description:
Plauger says:
  Description of locale::use() Effects contains a nonsense statement:
  ``Because locale objects are immutable, subsequent calls to use<Facet>()
  return the same object, regardless of changes to the global locale.''
 
  If a locale object is immutable, then changes to the global locale
  should *always* shine through, for any facet that is not present
  in the *this locale object. If the intent is to mandate caching
  semantics, as sketched out in the original locales proposal, this
  sentence doesn't quite succeed. Nor should it. Caching of facets
  found in the global locale leads to horribly unpredictable behavior,
  is unnecessary, and subverts practically any attempt to restoee
  compatibility with past C++ practice and the current C Standard.
  The sentence should be struck.
 
** Discussion:
locale objects are immutable in the sense that a call to use_facet<>
or has_facet<> on a given locale object always yields the same result.
If changing the global locale led to varying results from use_facet<>,
the objects could not be treated as immutable, and users could not
cache the result of use_facet<>.
 
Here is the invariant:  use_facet<facet>(loc) always yields the same
result for any locale value.
 
Here is what I see as the alternatives that maintain this:
1. Status quo:
  If it has been called successfully before, return the same value.
  Else, if the locale was constructed with such a facet, return it.
  Else, if the global locale has such a facet, return it.
  Else, throw bad_cast.
 
2. Strict:
  If the locale was constructed with such a facet, return it.
  Else, throw bad_cast.
 
3. Compromise:
  During construction of a locale (except copy), all facets found in
  the global locale, and not specified otherwise, are incorporated.
  Otherwise, same as (2).
 
(3) eliminates any possible confusion about the source of
the facet used.  It means that if a facet might not be present, and
you want to use the current global one instead, you can say so:
 
  const foo& f = use_facet<foo>(has_facet<foo>(loc) ? loc : locale());
 
This change substantially simplifies the semantics of use_facet,
without reducing its convenience.
 
** Proposed Resolution
Adopt (3), by adding a paragraph at the beginning of [lib.locale.cons]:
 
  For all constructors except locale(const locale&), any facet found
  in the current global locale at the time of construction, and not
  otherwise specified by arguments, becomes a part of the constructed
  locale.
 
And change the descriptions of use_facet<> and has_facet<> as follows:
 
  template <class Facet> const Facet& use_facet(const locale& loc);
 
  Get a reference to a facet of a locale.
  Returns: a reference to the corresponding facet of loc, if present.
  Throws: bad_cast if the facet is not present.
  Notes: if loc is (a copy of) locale::transparent(), returns a
   reference to the corresponding facet in locale().  The reference
   returned remains valid as long as any copy of the locale it came
   from exists.
 
And
 
  template <class Facet> bool has_facet(const locale& loc) throw();
 
  Returns: true if loc was constructed with the specified facet.
  Notes: Returns false when applied to (a copy of) locale::transparent().
 
** Requestor:      Plauger
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-038
** Title:          lifetime semantics unclear
** Sections:       22.1.1.3
** Status:         active
 
** Description:
Plauger says:
  Description of locale::use Notes uses the term ``value semantics''
  and the verb ``to last.'' Are either of these terms defined within
  the Standard? The sentence should be reworded, or struck since it's
  non-normative anyway.
 
** Discussion:
The intent is clear; we need normative language to express it.
 
** Proposed Resolution:
Editorial.
 
** Requestor:      Plauger
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-039
** Title:          transparent locale wanted in iostream
** Sections:       22.1.1.5
** Status:         active
 
** Description:
Plauger says:
  locale::transparent() Notes says ``The effect of imbuing this locale
  into an iostreams component is unspecified.'' If this is a normative
  statement, it doesn't belong in a Notes clause. And if it's intended
  to be normative, it should be struck. Imbuing a stream with
  locale::transparent() is the *only* way to restore the behavior
  of iostreams to that in effect for *every* C++ programming running
  today. It is also essential in providing compatible behavior with
  the C Standard. The sentence should be struck.
 
** Discussion:
It was specifically intended and stated in the enabling proposal
that imbuing a transparent locale should be forbidden to provide
operators << and >> stable semantics from locale objects,
incompatible with "transparent" behavior.
 
** Proposed resolution:
Editorial: the statement was intended to be normative.
 
** Requestor:      Plauger
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-042
** Title:          codecvt<>::do_convert
** Sections:       [lib.locale.codecvt], [lib.locale.codecvt.virtuals]
** Status:         active
 
** Description:
Plauger says:
  codecvt::do_convert says ``If no translation is needed (returns
  noconv), sets to_next equal to argument to.'' The previous paragraph
  strongly suggests that the function should also set from_next to
  from. Presumably, the program will call do_convert once, with nothing
  to convert. If it returns noconv, the program will omit future calls
  to do_convert. If that is the intended usage, then it should be
  permissible to call any instance of do_convert with (mostly)
  null pointers, to simplify such enquiries -- and the wording should
  make clear how to make such a test call.
 
** Discussion:
We shouldn't lard up do_convert with all kinds of special cases.
If it seems necessary, we can add more members.  We have identified
one such member:
 
  -  virtual bool do_always_noconv() const throw();
     bool always_noconv() const throw() { return do_always_noconv(); }
 
     Returns: true if every call to convert() will return noconv.  The
      base class implementation returns true.
 
To provide the semantics of the C library's mblen and MB_CUR_MAX,
we also need:
 
  -  virtual int do_length(const stateT&, const fromT*, const fromT*,
                           size_t) const throw();
     int length(const stateT&, const fromT* from, const fromT* from_end,
                size_t max) const throw()
       { return do_length(state, from,from_end,max); }
 
     Returns: returns (from_next-from) where from_next is the largest
      value in the range [from,from_end] such that the sequence of values
      in the range [from,from_next) represents max or fewer valid complete
      characters of type toT.  The base class implementation returns the
      lesser of max and (from_end-from).
 
  -  virtual int do_max_length() const throw();
     int max_length() const throw() { return do_max_len(); }
 
     Returns: the maximum value that length(state,from,from_end,1) can
       return for any range [from,from_end).
 
** Proposed Resolution:
Add the members defined above.  (As in other facets, the virtual
members are protected, the non-virtuals are public.)
 
** Requestor:      Plauger
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-043
** Title:          codecvt<>::do_convert "partial" semantics could be clearer
** Sections:       22.2.1.4.2 [lib.locale.codecvt.virtuals]
** Status:         active
 
** Description:
  codecvt::do_convert Returns says that the function returns partial
  if it ``ran out of space in the destination.'' But the function
  mbrtowc, for example, can consume the remaining source characters,
  beyond the last delivered character, and absorb them into the
  state. It would be a pity to require do_convert to undo this
  work. Should say that partial can also mean the function ran out
  of source characters partway through a conversion. Then
  clarify that, after a return of partial, the
  next call to do_convert should begin with any characters between
  from_next and from_end, of which there might be none.
 
** Discussion:
Characters absorbed into the state have been consumed, but
possibly not yet emitted, either because
 
  - there is not room to emit the converted character, or
  - the state does not yet represent a complete character.
 
convert() should return *partial* in either case.  Thus, if
there are no more characters available in the input sequence.
 
** Proposed Resolution:
Change the table entry for *partial* in [lib.locale.codecvt.virtuals]:
 
  partial          Not all source characters converted.
 
And add:
 
  Notes: a return value of *partial*, if (from_next==from_end),
    indicates that either the destination sequence has not absorbed
    all the converted toT values, or that additional fromT values
    are needed before another toT value can be produced.
 
** Requestor:      Plauger
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-044
** Title:          ios parameters restrict facet flexibility
** Sections:       [many]
** Status:         active
 
** Description:
Plauger says:
  Template class num_get defines the type ios as basic_ios<charT>,
  which it then uses widely to characterize parameters. Thus, this
  facet can be used *only* with iostreams classes that use the
  default traits ios_traits<charT>. Since the use of num_get is
  mandated for *all* basic_istream classes, this restriction rules out
  essentially any substitution of traits. Best fix is to make the
  ios parameter an ios_base parameter on all the do_get calls,
  then change ios accordingly. This is sufficient if
  setstate is moved to ios_base as proposed elsewhere. But it requires
  further fiddling for num_put if fill is moved *out* of ios_base,
  as also proposed. Must be fixed, one way or another.
 
  [Similarly for num_put, other facets]
 
** Discussion:
 
Plauger's comments are correct.
 
** Proposed Resolution:
 
All of:
 
1. Replace each parameter of type "ios_type&" in locale facet member
   functions with a parameter of type "ios_base&".
 
2. In facets num_put<>, time_put<>, and money_put<>, add another
   argument immediately after the "ios_base&" argument: "char_type fill".
 
3. Eliminate the member typedef "ios_type" from all locale facets.
 
Note that this proposal depends on setstate() to be a member of
ios_base, not basic_ios<>, as I believe has been proposed elsewhere.
 
** Requestor:      Plauger
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-045
** Title:          implementors may dislike parsing digit group separators
** Sections:       22.2.3.1
** Status:         active
 
** Description:
Plauger says:
  Description of numpunct says, ``For parsing, if the digits portion
  contains no thousands-separators, no grouping constraint is applied.''
  This suggests that thousands-separators are permitted in an input
  sequence, and that the grouping constraint is applied, but it is
  profoundly unclear on how this might be done. Allowing thousands-
  separators at all in input is risky -- requiring that grouping
  constraints be checked is an outrageous burden on implementors,
  for a payoff of questionable utility and desirability. Should
  remove any requirement for recognizing thoudands-separators and
  grouping on input. And the effect on output needs considerable
  clarification.
 
** Discussion:
The semantics described has been implemented, both in Tools.h++ and
in num_put<> and num_get<>.  It is hard to justify generating human-
readable numeric formats, and then failing to parse them.
 
Requested clarifications of effects on output are unspecified.
On input, if no grouping is permitted (numpunct<>::grouping
returns the empty string) thousands separators should not
be considered part of the input string.
 
It need not be specified how parsing is affected if the thousands
separator is (e.g.) a digit; the effect is undefined unless we
define it.
 
** Proposed Resolution:
Add to num_get<> and money_get<> specifications for members get():
 
  If the [numpunct<>|moneypunct<>] facet member grouping() returns
  the empty string, any thousands separator characters encountered
  in the input sequence are not considered part of the numeric format.
 
** Requestor:
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-046
** Title:          Locale facets for money/time/messages not liked
** Sections:       22.2.4
** Status:         active
 
** Description:
Plauger says:
  Template classes collate, time_get, time_put, money_get, money_put,
  money_punct, messages, and their support classes still have only
  sketchy semantics -- over a year after they were originally
  accepted into the draft. They are based on little or no prior
  art, and they present specification problems that can be addressed
  properly only with detailed descriptions, which do not seem to be
  forthcoming. Even if adequate wording were to magically appear
  on short notice, the public still deserves the courtesy of a
  proper review. For all these reasons, and more, the remainder
  of clause 22 from this point on should be struck.
 
** Discussion:
Unstated problems are impossible to respond to.
 
** Proposed Resolution:
No change.
 
** Requestor:
** Owner:
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-048
** Title:          numpunct<> not consistent with moneypunct<>
** Sections:       [lib.locale.numpunct], [lib.locale.moneypunct]
** Status:         active
 
** Description:
 
The facet numpunct<> members decimal_point() and thousands_sep()
return strings (actually basic_string<charT>), where the moneypunct<>
members of the same name return charT.  There is no good reason for
an inconsistency here.  We should change either one or the other.
 
** Discussion:
 
We could change the moneypunct<> facet to also return strings from
these members.  However, if it is desired to perform rigorous
parsing, it is better to prevent these separators from having
more than one character, in case the first character is matched
but the second is not.
 
** Proposed Resolution:
 
1. Change the interface for numpunct<> members
 
    do_thousands_sep, thousands_sep, do_decimal_point, and decimal_point
 
  to all return a value of type charT, like moneypunct members.
 
*OR*
 
2. Change the interface for moneypunct<> corresponding members
   to match numpunct<>, and return a basic_string<charT>.
 
Recommend (1).
 
** Requestor:
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-049
** Title:          money_get<> and money_put<> should use long double
** Sections:       [lib.locale.money.get], [lib.locale.money.put]
** Status:         active
 
** Description:
 
For maximum precision, the members of money_get<> and money_put<> should
use a long double representation in place of a double.
 
** Proposed Resolution:
 
Replace the arguments to members of money_get<> and money_put<>
of type double or double& with arguments of type long double or
long double&, respectively.
 
** Requestor:
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-050
** Title:          case of whitespace thousands separator needs clarification
** Sections:       [lib.locale.num.get], [lib.locale.money.get]
** Status:         active
 
** Description:
 
In some locales, the preferred thousands separator is a space.
We need to clarify how spaces in and around numeric sequences
are handled.
 
** Discussion:
 
Where the thousands separator is a whitespace character, two adjacent
whitespace characters must represent a normal end of the number; while
two commas, if comma is the separator, would be an error.  (The first
would be absorbed, leaving the second in the input sequence.)
 
Examples:  a) "123,456"  b) "123,456, "  c) "123 456"  d) "123 456  "
 
(b) is ill-formed, because the grouping constraint is not met, and the
final space is not consumed.  However, (d) is good, though again the
final space is not consumed.
 
I don't think any other special cases ("What if it's a digit?")
are necessary -- if we don't say, the effect is unspecified.
 
** Proposed Resolution:
Specify for both num_get<> and money_get<> members get():
 
  Note: if [numpunct|moneypunct]<>::thousands_sep() returns a
    whitespace character, and grouping() is non-empty, then
    that character following a digit, and followed by a non-digit,
    is consumed but not treated as a thousands separator.
 
 
** Requestor:
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-051
** Title:          do hex and octal numbers use grouping?
** Sections:       [lib.locale.num.get], [lib.locale.num.put]
** Status:         active
 
** Description:
 
The specification does not say whether octal and hexadecimal numbers
are formatted and parsed using the numpunct<>::grouping constraint,
and the thousands_sep() digit group separator.
 
** Discussion:
 
It doesn't say they are not used for hex and octal numbers,
so the status quo is they are used.
 
** Proposed Resolution:
Add a footnote to confirm that any specified grouping is applied for
octal and hexadecimal formats as well.
 
** Requestor:      Ramesh S. <remesh@modena.uunet.in>
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-052
** Title:          Is non-whitespace ios<>::fill() parsed?
** Sections:       [lib.locale.num.get], [lib.locale.money.get]
** Status:         active
 
** Description:
 
The specification for num_get does not say whether fill characters
inserted before or after numbers is required to be parsed by
num_get<>.
 
** Discussion:
 
The traditional answer is "no".
 
** Proposed Resolution:
Add a footnote to confirm that the set of parseable number formats
is unaffected by the value of the fill() member of basic_ios<>.
 
** Requestor:      Ramesh S. <remesh@modena.uunet.in>
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-053
** Title:          What does format "internal" mean for unsigned/bool/etc.?
** Sections:       [lib.locale.num.put]
** Status:         active
 
** Description:
 
The WP doesn't say what a format specification of "internal" means
for types which have no "interior".
 
** Discussion:
 
It would be reasonable to interpret it to mean either "left" or "right".
Ignoring it would be equivalent to "left".
 
** Proposed Resolution:
One of:
1. Same as left.
2. Same as right.
 
** Requestor:      Ramesh S. <ramesh@modena.uunet.in>
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-054
** Title:          should num_put<>::get(..., unsigned long) accept sign?
** Sections:       [lib.locale.num.get]
** Status:         active
 
** Description:
 
The WP isn't clear whether the sequence "-1" is a valid specification
of an unsigned integer, or what the resultant unsigned value should
be.  I believe scanf() accepts that sequence, but I don't know whether
all traditional iostream implementations do.
 
** Discussion:
 
We should match either the consensus of existing implementations,
if such exists, or scanf(), or what makes more sense, collectively.
 
** Proposed Resolution:
 
One of:
1. signs are recognized on unsigned integer formats.
2. signs are not recognized on unsigned integer formats.
 
** Requestor:
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-055
** Title:          Should moneypunct<> have positive and negative formats?
** Sections:       [lib.locale.moneypunct]
** Status:         active
 
** Description:
 
Ramesh points out that with the possibility of two different formats
for positive and negative values makes parsing of monetary values
indeterminate.
 
** Discussion:
 
Ramesh is correct.  We should consolidate the positive and negative
formats to eliminate this indeterminacy, or limit the responsibility
of money_get<> to parse formats if they differ.
 
** Proposed Resolution:
 
One of:
 
1. Replace the moneypunct<> members pos_format() and neg_format(),
   and the virtuals do_pos_format() and do_neg_format(), with member
   format() and virtual do_format().
2. Specify in num_get that the format specified by neg_format()
   is used to parse monetary values.
 
** Requestor:      Ramesh S. <ramesh@modena.uunet.in>
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-056
** Title:          What is the default monetary format?
** Sections:       [lib.locale.moneypunct]
** Status:         active
 
** Description:
 
The WP doesn't say what formats are specified by the base class
numpunct<>::do_pos_format and do_neg_format().
 
** Discussion:
 
The choice is rather arbitrary, but should probably match the
format for international monetary values.
 
** Proposed Resolution:
 
Specify that the default return value of numpunct<>::do_[pos|neg]_format()
is { symbol, sign, value, none }.
 
** Requestor:      Ramesh S. <ramesh@modena.uunet.in>
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-057
** Title:          money_put<> and _get<> facets missing from table
** Sections:       [lib.locale.category], [lib.locale.money.get],
                   [lib.locale.money.put]
** Status:         active
 
** Description:
 
In the table of locale facet categories, and the facets that
are required to be provided as part of each, the facets
money_[get|put]<[char|wchar_t],true> are not mentioned.
They either need to be added, or the second template parameter
eliminated in favor of an argument on the put() and get()
members.
[this is an Editorial Proposal.]
 
** Discussion:
It is easy to imagine code in which the choice of local
or international monetary format is made at runtime, so
a template parameter to num_put and num_get would make
such code unnecessarily clumsy.
 
** Proposed Resolution:
In both money_put<> and money_get<> (but not in moneypunct<>):
 
1. Eliminate the second template parameter "bool Intl = false",
   and the static const member "bool intl".
 
2. Add to the members money_get<>::get() and money_put<>::put()
   another argument, immediately after the "const locale&" argument,
   of type bool:
 
      ...const locale&, const bool intl, ...
 
   Specify that if true, the function uses the moneypunct<charT,true>
   facet, else it uses the moneypunct<charT,false> facet, of the locale
   argument to control [parsing|formatting].
 
** Requestor:
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-058
** Title:          locale constructors with null arguments unspecified.
** Sections:       [lib.locale.cons]
** Status:         active
 
** Description:
 
For those locale constructors that take a pointer, it is not
documented what happens if the pointer is 0.  Also, for those
constructors that take another locale and copy facets from it,
it is not specified what happens if it is the transparent
locale.
 
[this is an Editorial Proposal.]
 
** Discussion:
 
They should throw something.
 
** Proposed Resolution:
 
Add to each such constructor that takes a pointer argument: if the
pointer argument is 0, throws runtime_error.
 
Add to each constructor (except the copy constructor) that takes a
locale argument: if the locale argument is equal to (a copy of)
locale::transparent(), throws runtime_error.
 
** Requestor:
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-059
** Title:          ctype<char> static members should be declared throw().
** Sections:       [lib.locale.ctype.special], [lib.locale.ctype.char.members]
** Status:         active
 
** Description:
 
The static members of the facet ctype<char> table() and classic_table()
should be marked throw(), because their semantics cannot fail.
[this is an Editorial Proposal.]
 
** Discussion:
 
** Proposed Resolution:
 
Add to the declaration (both in the synopsis and the description)
of static members ctype<char>::table() and classic_table(), "throw()".
 
** Requestor:
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-060
** Title:          time_get::do_get_year spec more vague than necessary.
** Sections:       [lib.locale.time.get.virtuals]
** Status:         active
 
** Description:
 
The description of the response of time_get::do_get_year to a two-digit
year says it is "unspecified" whether or how two-digit year values are
interpreted.  This leaves implementations a little too much latitude.
[this is an Editorial Proposal.]
 
** Discussion:
 
It should be "implementation-defined".
 
** Proposed Resolution:
 
Change the description for do_get_year to say "It is implementation-
defined whether two-digit year numbers are accepted, and if so what
century they are assumed to lie in."
 
** Requestor:
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-061
** Title:          collate<> members should have ignore_case flag
** Sections:       [lib.locale.collate], [lib.locale.collate.virtuals]
** Status:         active
 
** Description:
This is from Art Kaufman <afk@ElSegundoCA.attgis.com>:
 
  We need to mix case-sensitive and case-insensitive comparisons throughout
  our system; juggling two named collate<> facets seems to be the only
  way to do this.  I find it very awkward.  I'd prefer to have a parameter
  to compare(), transform() and hash().
 
** Discussion:
 
We could add a bool parameter at the end of each member of collate<>.
This would provide a basis for basic_string<> members that ignore
case, which is perceived may many as a major deficiency in <string>.
 
** Proposed Resolution:
 
Add a final argument ", bool ignore_case = false" to each of:
 
  collate<>::do_compare
  collate<>::do_transform
  collate<>::do_hash
  collate<>::compare
  collate<>::transform
  collate<>::hash
 
and specify that each of compare, transform, and hash pass along
their argument to the corresponding virtual function.
 
** Requestor:      Art Kaufman <afk@ElSegundoCA.attgis.com>
** Owner:          Myers
 
---------------
 
** Work Group:     Library: Localization Clause 22
** Issue Number:   22-062
** Title:          ctype<char> member table() size overspecified
** Sections:       [lib.locale.ctype.char.members]
** Status:         active
 
** Description:
 
The size of the table used by ctype<char> is specified in the
WP to be of size UCHAR_MAX+1.  This may be an arbitrarily large
value, too large for practicality in some implementations.
 
** Discussion:
 
There is no reason all implementations need to have a table
this large, if it is large.
 
** Proposed Resolution:
Change the specification to say that the table has an
implementation-defined size, less than or equal to
numeric_limits<unsigned char>::max() + 1, sufficient to
map all valid character values.
 
** Requestor:
** Owner:          Myers
 
---------------
Closed issues:
 
** Issue Number:   22-001
** Title:          locale usage syntax "loc.template use<>()" too clumsy
** Resolution:     passed
 
** Issue Number:   22-002
** Title:          locale member constant "all" overconstrained.
** Resolution:     passed
 
** Issue Number:   22-003
** Title:          Effect of operators | and & on categories is unspecified.
** Resolution:     passed
 
** Issue Number:   22-005
** Title:          Locale operators shouldn't throw exceptions
** Resolution:     passed
 
** Issue Number:   22-006
** Title:          locale constructors should say they throw runtime_error
** Resolution:     passed
 
** Issue Number:   22-007
** Title:          locale template use() throw behavior needs clarification
** Resolution:     passed
 
** Issue Number:   22-008
** Title:          locale member op() needs more template parameters
** Resolution:     passed
 
** Issue Number:   22-010
** Title:          Convenience functions is???(c, const locale&) are slow
** Resolution:     editorial
 
** Issue Number:   22-011
** Title:          ctype_base member ctype_mask name is too long
** Resolution:     passed
 
** Issue Number:   22-012
** Title:          ctype<>::is(...) result inconsistent with other members
** Resolution:     passed
 
** Issue Number:   22-013
** Title:          ctype<char> derivation interface overconstrained.
** Resolution:     passed
 
** Issue Number:   22-014
** Title:          ctype_byname<char> specialization not described.
** Resolution:     passed
 
** Issue Number:   22-015
** Title:          codecvt<> usage could be better described
** Resolution:     passed
 
** Issue Number:   22-020
** Title:          collate virtuals description need editing
** Resolution:     passed
 
** Issue Number:   22-021
** Title:          time_get<> members need clarification
** Resolution:     passed
 
** Issue Number:   22-023
** Title:          time_put<>::put(... const char* ...) multibyte mistake
** Resolution:     passed
 
** Issue Number:   22-024
** Title:          money_get<> needs static const member intl
** Resolution:     passed
 
** Issue Number:   22-025
** Title:          Facet members string and ios are confusing
** Resolution:     passed
 
** Issue Number:   22-026
** Title:          money_get/put<> need control for currency symbol
** Resolution:     passed
 
** Issue Number:   22-027
** Title:          do_positive_sign and do_negative_sign are not right yet
** Resolution:     passed
 
** Issue Number:   22-028
** Title:          messages catalog identifier underspecified
** Resolution:     passed
 
** Issue Number:   22-029
** Title:          codecvt<>::convert boundary condition imprecise
** Resolution:     editorial
 
** Issue Number:   22-031
** Title:          locale inserter and extractor need sanction
** Resolution:     closed
 
** Issue Number:   22-032
** Title:          locale::category typedef should be int
** Resolution:     passed
 
** Issue Number:   22-033
** Title:          locale constructor has obscure provenance.
** Resolution:     closed
 
** Issue Number:   22-036
** Title:          categories facet list incomplete
** Resolution:     passed
 
** Issue Number:   22-040
** Title:          codecvt<> instantiation clarification
** Resolution:     closed
 
** Issue Number:   22-041
** Title:          do_convert uses 3 args where 2 would suffice.
** Resolution:     closed