______________________________________________________________________

  22   Localization library                 [lib.localization]

  ______________________________________________________________________

1 This clause describes components that C++ programs may use to encapsu­
  late  (and  therefore be more portable when confronting) cultural dif­
  ferences.  The locale facility includes  internationalization  support
  for  character classification and string collation, numeric, monetary,
  and date/time formatting and parsing, and message retrieval.

2 The following subclauses describe components for  locales  themselves,
  the  standard facets, and facilities from the ISO C library, as summa­
  rized in Table 1:

                  Table 1--Localization library summary

     +---------------------------------------------------------------+
     |                    Subclause                        Header(s) |
     +---------------------------------------------------------------+
     |_lib.locales_ Locales                                <locale>  |
     |_lib.locale.categories_ Standard locale Categories             |
     +---------------------------------------------------------------+
     |_lib.c.locales_ C library locales                    <clocale> |
     +---------------------------------------------------------------+

  22.1  Locales                                            [lib.locales]

  Header <locale> synopsis

  #include <limits>
  #include <string>
  #include <iosfwd>
  #include <stdexcept>    // for runtime_error

  namespace std {
  // subclause _lib.locale_, locale:
    class locale;
    template <class Facet> const Facet& use_facet(const locale&);
    template <class Facet> bool         has_facet(const locale&) throw();
    template <class charT, class Traits>
      basic_ostream<charT,Traits>&
        operator<<(basic_ostream<charT,Traits>& s, const locale& loc);
    template <class charT, class Traits>
      basic_istream<charT,Traits>&
        operator>>(basic_istream<charT,Traits>& s, locale& loc);

  // subclause _lib.locale.convenience_, convenience interfaces:
    template <class charT> bool isspace (charT c, const locale& loc) const;
    template <class charT> bool isprint (charT c, const locale& loc) const;
    template <class charT> bool iscntrl (charT c, const locale& loc) const;
    template <class charT> bool isupper (charT c, const locale& loc) const;
    template <class charT> bool islower (charT c, const locale& loc) const;
    template <class charT> bool isalpha (charT c, const locale& loc) const;
    template <class charT> bool isdigit (charT c, const locale& loc) const;
    template <class charT> bool ispunct (charT c, const locale& loc) const;
    template <class charT> bool isxdigit(charT c, const locale& loc) const;
    template <class charT> bool isalnum (charT c, const locale& loc) const;
    template <class charT> bool isgraph (charT c, const locale& loc) const;
    template <class charT> charT toupper(charT c, const locale& loc) const;
    template <class charT> charT tolower(charT c, const locale& loc) const;
  // subclauses _lib.category.ctype_ and _lib.facet.ctype.special_, ctype:
    class ctype_base;
    template <class charT> class ctype;
                           class ctype<char>;        // specialization
    template <class charT> class ctype_byname;
                           class ctype_byname<char>; // specialization
    class codecvt_base;
    template <class fromT, class toT, class stateT> class codecvt;
    template <class fromT, class toT, class stateT> class codecvt_byname;
  // subclauses _lib.category.numeric_ and _lib.facet.numpunct_, numeric:
    template <class charT, class InputIterator>  class num_get;
    template <class charT, class OutputIterator> class num_put;
    template <class charT> class numpunct;
    template <class charT> class numpunct_byname;
  // subclause _lib.category.collate_, collation:
    template <class charT> class collate;
    template <class charT> class collate_byname;
  // subclause _lib.category.time_, date and time:
    class time_base;
    template <class charT, class InputIterator>  class time_get;
    template <class charT, class InputIterator>  class time_get_byname;
    template <class charT, class OutputIterator> class time_put;
    template <class charT, class OutputIterator> class time_put_byname;
  // subclauses _lib.category.monetary_, money:
    class money_base;
    template <class charT, class InputIterator, bool Intl>  class money_get;
    template <class charT, class OutputIterator, bool Intl> class money_put;
    template <class charT, bool Intl> class moneypunct;
    template <class charT, bool Intl> class moneypunct_byname;
  // subclause _lib.category.messages_, message retrieval:
    class messages_base;
    template <class charT> class messages;
    template <class charT> class messages_byname;
  }

1 The header <locale> defines classes and declares functions that encap­
  sulate and manipulate the information peculiar to a locale.1)
  _________________________
  1)  In  this  subclause, the type name struct tm is an incomplete type
  that is defined in <ctime>.

  22.1.1  Class locale                                      [lib.locale]
  namespace std {
    class locale {
    public:
    // types:
      class facet;
      class id;
      typedef int category;
      static const category   // values assigned here are for exposition only
        none     = 0,
        collate  = 0x010, ctype    = 0x020,
        monetary = 0x040, numeric  = 0x080,
        time     = 0x100, messages = 0x200,
        all = collate | ctype | monetary | numeric | time  | messages;
    // construct/copy/destroy:
      locale() throw()
      locale(const locale& other) throw()
      explicit locale(const char* std_name);
      locale(const locale& other, const char* std_name, category);
      template <class Facet> locale(const locale& other, Facet* f);
      template <class Facet> locale(const locale& other,
                                    const locale& one);
      locale(const locale& other, const locale& one, category);
     ~locale() throw();  // non-virtual
      const locale& operator=(const locale& other) throw();
    // locale operations:
      basic_string<char>                  name() const;
      bool operator==(const locale& other) const;
      bool operator!=(const locale& other) const;
      template <class charT,Traits>
        bool operator()(const basic_string<charT,Traits>& s1,
                        const basic_string<charT,Traits>& s2) const;
    // global locale objects:
      static       locale  global(const locale&);
      static const locale& classic();
      static       locale  transparent();
    };
  }

1 Class locale implements a type-safe polymorphic set of facets, indexed
  by facet type.  In other words, a facet has a dual role: in one sense,
  it's just a class interface; at the same time, it's an  index  into  a
  locale's set of facets.

2 Access to the facets of a locale is via two member function templates,
  use_facet<> and has_facet<>.

3 [Example: An iostream operator<< might be implemented as:2)

  _________________________
  2) Notice that, in the call to put, the stream is implicitly converted
  to an ostreambuf_iterator<charT,traits>.

    template <class charT, class traits>
      basic_ostream<charT,traits>&
      operator<< (basic_ostream<charT,traits>& s, Date d)
    {
      typename basic_ostream<charT,traits>::sentry cerberos;
      if (cerberos) {
        ios_base::iostate err = 0;
        tm tmbuf; d.extract(tmbuf);
        use_facet< time_put<charT,ostreambuf_iterator<charT,traits> > >(
          s.getloc()).put(s, s, s.fill(), err, &tmbuf, 'x');
        s.setstate(err);  // might throw
      }
      return s;
    }
   --end example]

4 In  the  call  to  use_facet<Facet>(loc),  the type argument chooses a
  facet, making available all members of the named type. If Facet is not
  present  in  a  locale  (or,  failing  that, in the global locale), it
  throws the standard exception bad_cast.  A C++ program can check if  a
  locale  implements  a  particular  facet  with  the  template function
  has_facet<Facet>().  User-defined facets may be installed in a locale,
  and used identically as may standard facets (_lib.facets.examples_).

5 [Note:   All   locale  semantics  are  accessed  via  use_facet<>  and
  has_facet<>, except that:

  --A   member    operator    template    operator()(basic_string<C,T>&,
    basic_string<C,T>&)  is  provided  so that a locale may be used as a
    predicate argument to the standard collections, to collate  strings.

  --Convenient  global  interfaces  are  provided  for traditional ctype
    functions such as isdigit() and isspace(), so that  given  a  locale
    object  loc  a  C++  program  can  call isspace(c,loc).  (This eases
    upgrading existing extractors  (_lib.istream.formatted_).)     --end
    note]

6 A  locale  which  does  not  implement a facet delegates to the global
  locale in effect at the time  that  instantiation  of  use_facet<>  is
  first called on that facet (_lib.locale.statics_).

7 An instance of locale is immutable; once a facet reference is obtained
  from it, that reference remains usable as long  as  the  locale  value
  itself  exists.   The  effect  of imbuing on a stream (_lib.ios.base_,
  _lib.ios_), or installing as the global locale, the result  of  static
  member  locale::transparent() (or any locale with similar behavior) is
  unspecified.

8 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
  (_lib.streambuf_).3)
  _________________________
  3) This implies that member functions of iostream classes cannot safe­

9 A locale constructed from a name string (such  as  "POSIX"),  or  from
  parts  of  two  named  locales, or read from a stream, has a name; all
  others do not.  Named locales may be compared for equality; an unnamed
  locale  is  equal  only to (copies of) itself.  For an unnamed locale,
  locale::name() returns the string *".

  22.1.1.1  locale types                              [lib.locale.types]

  22.1.1.1.1  Type locale::category                [lib.locale.category]

  typedef int category;

1 Valid category values include the locale member bitmask elements none,
  collate,  ctype,  monetary, numeric, time, and messages.  In addition,
  locale member all is defined such that the expression
    (collate | ctype | monetary | numeric | time | messages | all) == all
  is true.  Further, the result of applying operators | and & to any two
  valid  values is valid, and results in the setwise union and intersec­
  tion, respectively, of the argument categories.

2 locale member functions expecting a category argument require either a
  valid category value or one of the constants LC_CTYPE etc., defined in
  <cctype>.  Such a category value identifies  a  set  of  locale  cate­
  gories.   Each  locale  category,  in turn, identifies a set of locale
  facets, including at least those shown in Table 2:

  _________________________
  ly call imbue() themselves, except as specified elsewhere.

                     Table 2--Locale Category Facets

      +------------------------------------------------------------+
      |Category                   Includes Facets                  |
      +------------------------------------------------------------+
      |collate    collate<char>, collate<wchar_t>                  |
      +------------------------------------------------------------+
      |ctype      ctype<char>, ctype<wchar_t>                      |
      |           codecvt<char,char,mbstate_t>,                    |
      |           codecvt<char,wchar_t,mbstate_t>,                 |
      |           codecvt<wchar_t,char,mbstate_t>                  |
      +------------------------------------------------------------+
      |monetary   moneypunct<char>, moneypunct<wchar_t>            |
      |           moneypunct<char,true>, moneypunct<wchar_t,true>, |
      |           money_get<char>, money_get<wchar_t>              |
      |           money_get<char,true>, money_get<wchar_t,true>    |
      |           money_put<char>, money_put<wchar_t>              |
      |           money_put<char,true>, money_put<wchar_t,true>    |
      +------------------------------------------------------------+
      |numeric    numpunct<char>, numpunct<wchar_t>,               |
      |           num_get<char>, num_get<wchar_t>                  |
      |           num_put<char>, num_put<wchar_t>                  |
      +------------------------------------------------------------+
      |time       time_get<char>, time_put<wchar_t>,               |
      |           time_put<char>, time_put<wchar_t>                |
      +------------------------------------------------------------+
      |messages   messages<char>, messages<wchar_t>                |
      +------------------------------------------------------------+

  +-------                 BEGIN BOX 1                -------+
  Change:    Added    money_get<char,true>,     money_get<wchar_t,true>,
  money_put<char,true>,   and   money_put<wchar_t,true>.   (The  WG  has
  elected not to change the signatures of the  money_get  and  money_put
  facets and member functions.)
  +-------                  END BOX 1                 -------+

3 For    any   locale   loc   either   constructed,   or   returned   by
  locale::classic(), and any facet Facet that is a member of a  standard
  category,  has_facet<Facet>(loc) is true.  Each locale member function
  which takes a locale::category argument operates on the  corresponding
  set of facets.

4 An  implementation  is  required  to  provide those instantiations for
  facet templates identified as members of a  category,  and  for  those
  shown in Table 3:

                     Table 3--Required Instantiations

     +---------------------------------------------------------------+
     |Category                     Includes Facets                   |
     +---------------------------------------------------------------+
     |collate    collate_byname<char>, collate_byname<wchar_t>       |
     +---------------------------------------------------------------+
     |ctype      ctype_byname<char>, ctype_byname<wchar_t>           |
     +---------------------------------------------------------------+
     |monetary   moneypunct_byname<char,International>,              |
     |           moneypunct_byname<wchar_t,International>,           |
     |           money_get<char,International,InputIterator>,        |
     |           money_get<wchar_t,International,InputIterator>,     |
     |           money_put<char,International,OutputIterator>,       |
     |           money_put<wchar_t,International,OutputIterator>     |
     +---------------------------------------------------------------+
     |numeric    numpunct_byname<char>, numpunct_byname<wchar_t>     |
     |           num_get<C,InputIterator>, num_put<C,OutputIterator> |
     +---------------------------------------------------------------+
     |time       time_get<char,InputIterator>,                       |
     |           time_get_byname<char,InputIterator>,                |
     |           time_get<wchar_t,OutputIterator>,                   |
     |           time_get_byname<wchar_t,OutputIterator>,            |
     |           time_put<char,OutputIterator>,                      |
     |           time_put_byname<char,OutputIterator>,               |
     |           time_put<wchar_t,OutputIterator>                    |
     |           time_put_byname<wchar_t,OutputIterator>             |
     +---------------------------------------------------------------+

5 For  the  facets  num_get<>  and num_put<> the implementation provided
  must depend only on the corresponding facets numpunct<>  and  ctype<>,
  instantiated  on the same character type.  Other facets are allowed to
  depend on any other facet that is part of a standard category.

6 In declarations of facets,  a  template  formal  parameter  with  name
  InputIterator  or  OutputIterator  indicates  the  set of all possible
  instantiations on parameters that satisfy the requirements of an Input
  Iterator       or      an      Output      Iterator,      respectively
  (_lib.iterator.requirements_).  A template formal parameter with  name
  C  represents  the  set  of all possible instantiations on a parameter
  that satisfies the requirements for a character on which  any  of  the
  iostream components can be instantiated.

  22.1.1.1.2  Class locale::facet                     [lib.locale.facet]

  namespace std {
    class locale::facet {
    protected:
      explicit facet(size_t refs = 0);
      virtual ~facet();
    private:
      facet(const facet&);          // not defined
      void operator=(const facet&); // not defined
    };
  }

1 Class  facet  is the base class for locale feature sets.  A class is a
  facet if it is publicly derived from another facet,  or  if  it  is  a
  class  derived from locale::facet and containing a declaration as fol­
  lows:
        static ::std::locale::id id;
  Template parameters in this Clause which  must  be  facets  are  those
  named Facet in declarations.  A program that passes a type that is not
  a facet, as an (explicit or deduced) template parameter  to  a  locale
  function expecting a facet, is ill-formed.

2 The  refs argument to the constructor is used for lifetime management.

  --If (refs == 0) the facet's lifetime is  managed  by  the  locale  or
    locales it is incorporated into;

  --if (refs == 1) its lifetime is until explicitly deleted.

3 Constructors  of  all facets defined in this Clause take such an argu­
  ment and pass it along to their facet  base  class  constructor.   All
  one-argument  constructors  defined  in this clause are explicit, pre­
  venting their participation in automatic conversions.

4 For some standard facets a standard _byname" class, derived  from  it,
  implements  the virtual function semantics equivalent to that facet of
  the locale constructed by locale(const  char*)  with  the  same  name.
  Each  such facet provides a constructor that takes a const char* argu­
  ment, which names the locale, and a refs argument, which is passed  to
  the  base  class  constructor.   If  there is no _byname" version of a
  facet, the base class implements named locale semantics itself by ref­
  erence to other facets.

  22.1.1.1.3  Class locale::id                           [lib.locale.id]
  namespace std {
    class locale::id {
    public:
      id();
    private:
      void operator=(const id&); // not defined
      id(const id&);             // not defined
    };
  }

1 The  class locale::id provides identification of a locale facet inter­
  faces, used as an index for lookup and to encapsulate  initialization.

2 [Note:  Because facets are used by iostreams, potentially while static
  constructors are running, their initialization cannot depend  on  pro­
  grammed  static  initialization.   One  initialization strategy is for
  locale to initialize each facet's id member the first time an instance
  of  the facet is installed into a locale.  This depends only on static
  storage being zero before  constructors  run  (_basic.start.init_).
  --end note]

  22.1.1.2  locale constructors and destructor         [lib.locale.cons]

  locale() throw();

1 Default constructor: a snapshot of the current global locale.
  Effects:
    Constructs    a    copy    of    the   argument   last   passed   to
    locale::global(locale&), if it has been called; else, the  resulting
    facets  have  virtual  function  semantics  identical  to  those  of
    locale::classic().  [Note: This constructor is commonly used as  the
    default  value  for arguments of functions that take a const locale&
    argument.   --end note]

  locale(const locale& other) throw();

  Effects:
    Constructs a locale which is a copy of other.

  const locale& operator=(const locale& other) throw();

  Effects:
    Creates a copy of other, replacing the current value.
  Returns:
    *this

  explicit locale(const char* std_name);

  Effects:
    Constructs a locale using standard C  locale  names,  e.g.  "POSIX".
    The  resulting  locale implements semantics defined to be associated
    with that name.  Throws runtime_error if the argument is not  valid.
  Notes:
    The  set  of valid string argument values is "C", "", and any imple­
    mentation-defined values.

  locale(const locale& other, const char* std_name, category);

  Effects:
    Constructs a locale as a copy of other except for the facets identi­
    fied  by  the  category  argument,  which instead implement the same
    semantics as locale(std_name).
  Notes:
    The locale has a name if and only if other has a name.

  template <class Facet> locale(const locale& other, Facet* f);

  Effects:
    Constructs a locale incorporating all facets from the first argument
    except  that  of type Facet, and installs the second argument as the
    remaining facet.
  Notes:
    The resulting locale has no name.

  +-------                 BEGIN BOX 2                -------+
  Editorial proposal: What if the pointer parameter  is  0?   Recommend:
  Throw runtime_error.
  +-------                  END BOX 2                 -------+

  template <class Facet> locale(const locale& other, const locale& one);

  Effects:
    Constructs a locale incorporating all facets from the first argument
    except that identified by Facet, and  that  facet  from  the  second
    argument instead.
  Throws:
    runtime_error if has_facet<Facet>(one) is false.
  Notes:
    The resulting locale has no name.

  locale(const locale& other, const locale& one, category cats);

  Effects:
    Constructs a locale incorporating all facets from the first argument
    except those that implement cats,  which  are  instead  incorporated
    from the second argument.
  Notes:
    The  resulting  locale has a name if and only if the first two argu­
    ments have names.

  ~locale() throw();

2 A non-virtual destructor that throws no exceptions.

  22.1.1.3  locale members                          [lib.locale.members]

  basic_string<char>  name() const;

  Returns:
    The name of *this, if it has one; otherwise, the string "*".

  22.1.1.4  locale operators                      [lib.locale.operators]

  bool operator==(const locale& other) const;

  Returns:
    true if both arguments are the same locale, or one is a copy of  the
    other,  or each has a name and the names are identical; false other­
    wise.

  bool operator!=(const locale& other) const;

  Returns:
    The result of the expression: !(*this == other)

  template <class charT, class Traits>
    bool operator()(const basic_string<charT,Traits>& s1,
                    const basic_string<charT,Traits>& s2) const;

  Effects:
    Compares two strings according to the collate<charT> facet.
  Notes:
    This member operator template (and therefore locale  itself)  satis­
    fies  requirements  for  a  comparator  predicate  template argument
    (_lib.algorithms_) applied to strings.
  Returns:
    The result of the following expression:
      use_facet< collate<charT> >(*this).compare(s1.data(), s1.data()+s1.size(),
                                                 s2.data(), s2.data()+s2.size()) < 0;

1 [Example: A vector of strings v can be collated according to collation
  rules in locale loc simply by (_lib.alg.sort_, _lib.vector_):
    std::sort(v.begin(), v.end(), loc);
   --end example]

  22.1.1.5  locale static members                   [lib.locale.statics]

  static locale global(const locale& loc);

1 Sets the global locale to its argument.

  Effects:
    Causes  future calls to the constructor locale() to return a copy of
    the argument.  If the argument has a name, does
        std::setlocale(LC_ALL, loc.name().c_str());
    otherwise, the effect on the C locale, if  any,  is  implementation-
    defined.   If  the  argument  is  (a  copy of) the value returned by
    locale::transparent(), throws runtime_error.
  Returns:
    The previous value of locale().

  static const locale& classic();

2 The "C" locale.
  Returns:
    A locale that implements the classic "C" locale  semantics,  equiva­
    lent to the value locale("C").
  Notes:
    This  locale,  its facets, and their member functions, do not change
    with time.

  static locale transparent();

3 The continuously updated global locale.
  Returns:
    A locale which implements semantics that  vary  dynamically  as  the
    global locale is changed.
  Notes:
    The  effect  of  imbuing  this locale into an iostreams component is
    unspecified (_lib.ios.members_).

  22.1.2  locale globals                   [lib.locale.global.templates]

  template <class Facet> const Facet& use_facet(const locale& loc);

1 Get a reference to a facet of a locale.
  Effects:
    If the requested Facet is not present in loc, but is present in  the
    current  global  locale,  returns  the  global  locale's instance of
    Facet.  Because locale objects are immutable,  subsequent  calls  to
    use_facet<Facet>(loc)  return  the same object, regardless of subse­
    quent calls to setlocale or locale::global.
  Notes:
    The only exception to this  rule  is  for  the  locale  returned  by
    locale::transparent();  it  always  returns  the  facet found in the
    global locale at the time of each call.
  Throws:
    bad_cast if (has_facet<Facet>(*this) ||  has_facet<Facet>(locale()))

    is false, or other unspecified objects catchable as exception.
  Returns:
    A reference to the requested facet.
  Notes:
    The result is guaranteed by locale's value semantics to last as long
    as the value of loc.

  +-------                 BEGIN BOX 3                -------+
  Is bad_cast the best choice of exceptions to throw?
  +-------                  END BOX 3                 -------+

  template <class Facet> bool has_facet(const locale& loc) throw();

  Returns:
    An indication whether the facet requested is  present  in  loc.   If
    use_facet<Facet>(loc)  has already been called successfully, returns
    true.
  Notes:
    has_facet<Facet>(locale::transparent()) always returns false.

  template <class charT, class Traits>
    basic_ostream<charT,Traits>&
      operator<<(basic_ostream<charT,Traits>& s, const locale& loc);

2 The     regular     stream     output     operator     for     locales
  (_lib.ostream.formatted_).
  Effects:
    s << loc.name() << endl.
  Returns:
    The output stream argument s.

  template <class charT, class Traits>
    basic_istream<charT,Traits>&
      operator>>(basic_istream<charT,Traits>& s, locale& loc);

3 The      regular     stream     input     operator     for     locales
  (_lib.istream.formatted_).
  Effects:
    Read a line into a string and construct a locale from it.  If either
    operation     fails,     indicates     a    failure    by    calling
    s.setstate(ios_base::failbit)  (which  may  throw  ios_base::failure
    (_lib.iostate.flags_),  otherwise,  assigns  the  constructed locale
    object into the argument loc.
  Returns:
    s.

  22.1.3  Convenience interfaces                [lib.locale.convenience]

  22.1.3.1  Character classification                [lib.classification]

  template <class charT> bool isspace (charT c, const locale& loc) const;
  template <class charT> bool isprint (charT c, const locale& loc) const;
  template <class charT> bool iscntrl (charT c, const locale& loc) const;
  template <class charT> bool isupper (charT c, const locale& loc) const;
  template <class charT> bool islower (charT c, const locale& loc) const;
  template <class charT> bool isalpha (charT c, const locale& loc) const;
  template <class charT> bool isdigit (charT c, const locale& loc) const;
  template <class charT> bool ispunct (charT c, const locale& loc) const;
  template <class charT> bool isxdigit(charT c, const locale& loc) const;
  template <class charT> bool isalnum (charT c, const locale& loc) const;
  template <class charT> bool isgraph (charT c, const locale& loc) const;

1 Each of these functions isF returns the result of the expression:
    use_facet< ctype<charT> >(loc).is(ctype_base::F, c)
  where F is the ctype_base::mask value corresponding to  that  function
  (_lib.category.ctype_).4)

  22.1.3.2  Character conversions                      [lib.conversions]

  template <class charT> charT toupper(charT c, const locale& loc) const;

  Returns:
    use_facet<ctype<charT> >(loc).toupper(c).

  template <class charT> charT tolower(charT c, const locale& loc) const;

  Returns:
    use_facet<ctype<charT> >(loc).tolower(c).

  22.2  Standard locale categories               [lib.locale.categories]

1 Each of the standard categories includes a family of facets.  Some  of
  these  implement formatting or parsing of a datum, for use by standard
  or users' iostream operators << and >>, as members  put()  and  get(),
  respectively.   Each  such member function takes an ios_base& argument
  whose members flags(), precision(), and width(), specify the format of
  the  corresponding  datum.   (_lib.ios.base_).   Those functions which
  need to use other facets call its  member  getloc()  to  retrieve  the
  locale  imbued  there.   Formatting  facets use the character argument
  fill to fill out the specified width where necessary.

  _________________________
  4)  When  used  in a loop, it is faster to cache the ctype<> facet and
  use it directly, or use the vector form of ctype<>::is.

2
  +-------                 BEGIN BOX 4                -------+
  Editorial Proposal: If clear() and setstate() are moved  to  ios_base,
  we should add:
  The  put()  and  get()  members  do  not use rdstate(), setstate(), or
  related members of the ios_base& argument.
  +-------                  END BOX 4                 -------+

  The put() members make no provision for error reporting.   (Any  fail­
  ures  of  the  OutputIterator  argument  must  be  extracted  from the
  returned iterator.)  The  get()  members  take  an  ios_base::iostate&
  argument whose value they ignore, but set to ios_base::failbit in case
  of a parse error.

  22.2.1  The ctype category                        [lib.category.ctype]
  namespace std {
    class ctype_base {
    public:
      enum mask {  // numeric values are for exposition only.
        space=1<<0, print=1<<1, cntrl=1<<2, upper=1<<3, lower=1<<4,
        alpha=1<<5, digit=1<<6, punct=1<<7, xdigit=1<<8,
        alnum=alpha|digit, graph=alnum|punct
      };
    };
  }

1 The type mask is a bitmask type.

  22.2.1.1  Template class ctype                      [lib.locale.ctype]
    template <class charT>
    class ctype : public locale::facet, public ctype_base {
    public:
      typedef charT char_type;
      explicit ctype(size_t refs = 0);
      bool         is(mask m, charT c) const;
      const charT* is(const charT* low, const charT* high, mask* vec) const;
      const charT* scan_is(mask m,
                           const charT* low, const charT* high) const;
      const charT* scan_not(mask m,
                            const charT* low, const charT* high) const;
      charT        toupper(charT) const;
      const charT* toupper(charT* low, const charT* high) const;
      charT        tolower(charT c) const;
      const charT* tolower(charT* low, const charT* high) const;
      charT        widen(char c) const;
      const char*  widen(const char* low, const char* high, charT* to) const;
      char         narrow(charT c, char dfault) const;
      const charT* narrow(const charT* low, const charT*, char dfault,
                          char* to) const;
      static locale::id id;

    protected:
     ~ctype();  // virtual
      virtual bool         do_is(mask m, charT c) const;
      virtual const charT* do_is(const charT* low, const charT* high,
                                 mask* vec) const;
      virtual const charT* do_scan_is(mask m,
                                      const charT* low, const charT* high) const;
      virtual const charT* do_scan_not(mask m,
                                       const charT* low, const charT* high) const;
      virtual charT        do_toupper(charT) const;
      virtual const charT* do_toupper(charT* low, const charT* high) const;
      virtual charT        do_tolower(charT) const;
      virtual const charT* do_tolower(charT* low, const charT* high) const;
      virtual charT        do_widen(char) const;
      virtual const char*  do_widen(const char* low, const char* high,
                                    charT* dest) const;
      virtual char         do_narrow(charT, char dfault) const;
      virtual const charT* do_narrow(const charT* low, const charT* high,
                                     char dfault, char* dest) const;
    };

  +-------                 BEGIN BOX 5                -------+
  Change: Changed return type of do_scan_is  and  do_scan_not  to  const
  charT* to match the semantic description of the function.
  +-------                  END BOX 5                 -------+

1 Class  ctype  encapsulates  the  C library <cctype> features.  istream
  members are required to use  ctype<>  for  character  classing  during
  input parsing.

2 The  base class implementation implements character classing appropri­
  ate to the implementation's native character set.

  22.2.1.1.1  ctype members                   [lib.locale.ctype.members]

  bool         is(mask m, charT c) const;
  const charT* is(const charT* low, const charT* high,
                  mask* vec) const;

  Returns:
    do_is(m,c) or do_is(low,high,vec)

  const charT* scan_is(mask m,
                       const charT* low, const charT* high) const;

  Returns:
    do_scan_is(m,low,high)

  const charT* scan_not(mask m,
                        const charT* low, const charT* high) const;

  Returns:
    do_scan_not(m,low,high)

  charT        toupper(charT) const;
  const charT* toupper(charT* low, const charT* high) const;

  Returns:
    do_toupper(c) or do_toupper(low,high)

  charT        tolower(charT c) const;
  const charT* tolower(charT* low, const charT* high) const;

  Returns:
    do_tolower(c) or do_tolower(low,high)

  charT       widen(char c) const;
  const char* widen(const char* low, const char* high, charT* to) const;

  Returns:
    do_widen(c) or do_widen(low,high,to)

  char         narrow(charT c, char dfault) const;
  const charT* narrow(const charT* low, const charT*, char dfault,
                      char* to) const;

  Returns:
    do_narrow(c,dfault) or do_narrow(low,high,dfault,to)

  22.2.1.1.2  ctype virtual functions        [lib.locale.ctype.virtuals]

  bool         do_is(mask m, charT c) const;
  const charT* do_is(const charT* low, const charT* high,
                     mask* vec) const;

  Effects:
    Classifies a character or sequence of characters.  For each argument
    character,  identifies a value M of type ctype_base::mask.  The sec­
    ond form places M for all *p where (low<=p && p<high),  into  vec[p-
    low].
  Returns:
    The  first  form  returns the result of the expression (M & m) != 0;
    i.e., true if the character has the characteristics specified.   The
    second form returns high.

  const charT* do_scan_is(mask m,
                         const charT* low, const charT* high) const;

  Effects:
    Locates a character in a buffer that conforms to a classification m.
  Returns:
    The smallest pointer p in the range [low,  high)  such  that  is(*p)
    would return true; otherwise, returns high.

  const charT* do_scan_not(mask m,
                          const charT* low, const charT* high) const;

  Effects:
    Locates a character in a buffer that fails to conform to a classifi­
    cation m.
  Returns:
    The smallest pointer p, if any, in the range [low, high)  such  that
    is(*p) would return false; otherwise, returns high.

  charT        do_toupper(charT c) const;
  const charT* do_toupper(charT* low, const charT* high) const;

  Effects:
    Converts  a  character or characters to upper case.  The second form
    replaces each character *p in the range [low, high) for which a cor­
    responding upper-case character exists, with that character.
  Returns:
    The  first form returns the corresponding upper-case character if it
    is known to exist, or its argument if not.  The second form  returns
    high.

  charT        do_tolower(charT c) const;
  const charT* do_tolower(charT* low, const charT* high) const;

  Effects:
    Converts  a  character or characters to upper case.  The second form
    replaces each character *p in the range [low, high) and for which  a
    corresponding lower-case character exists, with that character.
  Returns:
    The  first form returns the corresponding lower-case character if it
    is known to exist, or its argument if not.  The second form  returns
    high.

  charT        do_widen(char c) const;
  const char*  do_widen(const char* low, const char* high,
                        charT* dest) const;

  Effects:
    Applies  the simplest reasonable transformation from a char value or

    sequence of char values to the corresponding charT value or  values.
    The  only  characters  for which unique transformations are required
    are the digits, alphabetic characters, '-', '+', newline, and space.
    For any named ctype category with a ctype<charT> facet ctw and valid
    ctype_base::mask value M (is(M, c) || !ctw.is(M, do_widen(c))  )  is
    true.5)
    The second form transforms each character  *p  in  the  range  [low,
    high), placing the result in dest[p-low].
  Returns:
    The  first  form  returns  the  transformed  value.  The second form
    returns high.

  char         do_narrow(charT c, char dfault) const;
  const charT* do_narrow(const charT* low, const charT* high,
                         char dfault, char* dest) const;

  Effects:
    Applies the simplest reasonable transformation from a charT value or
    sequence  of charT values to the corresponding char value or values.
    The only characters for which unique  transformations  are  required
    are the digits, alphabetic characters, '-', '+', newline, and space.
    For any named ctype category with a ctype<char> facet  ctc  however,
    and ctype_base::mask value M,
        (is(M,c) || !ctc.is(M, do_narrow(c),dfault) )"
    is  true  (unless  do_narrow  returns dfault).  In addition, for any
    digit character c, the expression  (do_narrow(c,dfault)-'0')  evalu­
    ates  to  the  digit value of the character.  The second form trans­
    forms each character *p in the range [low, high), placing the result
    (or  dfault  if  no  simple  transformation  is readly available) in
    dest[p-low].
  Returns:
    The first form returns the transformed value; or dfault if  no  map­
    ping is readily available.  The second form returns high.

  22.2.1.2  Template class ctype_byname        [lib.locale.ctype.byname]

  _________________________
  5)  In  other  words, the transformed character is not a member of any
  character classification that c is not also a member of.

    template <class charT>
    class ctype_byname : public ctype<charT> {
    public:
      explicit ctype_byname(const char*, size_t refs = 0);
    protected:
     ~ctype_byname();  // virtual
      virtual bool         do_is(mask m, charT c) const;
      virtual const charT* do_is(const charT* low, const charT* high,
                                 mask* vec) const;
      virtual const char*  do_scan_is(mask m,
                                      const charT* low, const charT* high) const;
      virtual const char*  do_scan_not(mask m,
                                       const charT* low, const charT* high) const;
      virtual charT        do_toupper(charT) const;
      virtual const charT* do_toupper(charT* low, const charT* high) const;
      virtual charT        do_tolower(charT) const;
      virtual const charT* do_tolower(charT* low, const charT* high) const;
      virtual charT        do_widen(char) const;
      virtual const char*  do_widen(const char* low, const char* high,
                                    charT* dest) const;
      virtual char         do_narrow(charT, char dfault) const;
      virtual const charT* do_narrow(const charT* low, const charT* high,
                                     char dfault, char* dest) const;
    };
  }

  22.2.1.3  ctype specializations              [lib.facet.ctype.special]
  namespace std {
    class ctype<char> : public locale::facet, public ctype_base {
    public:
      typedef char char_type;
      explicit ctype(const mask* tab = 0, bool del = false,
                     size_t refs = 0);
      bool is(mask m, char c) const;
      const char* is(const char* low, const char* high, mask* vec) const;
      const char* scan_is (mask m,
                           const char* low, const char* high) const;
      const char* scan_not(mask m,
                           const char* low, const char* high) const;
      char        toupper(char c) const;
      const char* toupper(char* low, const char* high) const;
      char        tolower(char c) const;
      const char* tolower(char* low, const char* high) const;
      char  widen(char c) const;
      const char* widen(const char* low, const char* high, char* to) const;
      char  narrow(char c, char dfault) const;
      const char* narrow(const char* low, const char* high, char dfault,
                         char* to) const;
      static locale::id id;
    protected:
      const mask* table() const throw();
      static const mask* classic_table() throw();

     ~ctype();  // virtual
      virtual char        do_toupper(char) const;
      virtual const char* do_toupper(char* low, const char* high) const;
      virtual char        do_tolower(char) const;
      virtual const char* do_tolower(char* low, const char* high) const;
    };
  }

1 A  specialization ctype<char> is provided so that the member functions
  on type char can be implemented inline.6)

  22.2.1.3.1  ctype<char> destructor         [lib.facet.ctype.char.dtor]

  ~ctype();

  Effects:
    If  the  constructor's  first  argument  was nonzero, and its second
    argument was true, does delete [] table().

  22.2.1.3.2  ctype<char> members         [lib.facet.ctype.char.members]

  explicit ctype(const mask* tab = 0, bool del = false,
                 size_t refs = 0);

  Effects:
    Passes its refs argument to its base class constructor.

  bool        is(mask m, char c) const;
  const char* is(const char* low, const char* high,
                 mask* vec) const;

  Effects:
    The second form, for all *p in the range [low, high), assigns vec[p-
    low] to table()[(unsigned char)*p].
  Returns:
    The  first  form  returns  table()[(unsigned char)c] & m; the second
    form returns high.

  const char* scan_is(mask m,
                      const char* low, const char* high) const;

  Returns:
    The smallest p in the range [low, high) such that
  _________________________
  6) Only the char (not unsigned char and signed char) form is provided.
  The  specialization  is  specified in the standard, and not left as an
  implementation detail, because it affects the derivation interface for
  ctype<char>.

      table()[(unsigned char) *p] & m
    is true.

  const char* scan_not(mask m,
                       const char* low, const char* high) const;

  Returns:
    The smallest p in the range [low, high) such that
      table()[(unsigned char) *p] & m
    is false.

  char        toupper(char c) const;
  const char* toupper(char* low, const char* high) const;

  Returns:
    do_toupper(c) or do_toupper(low,high)

  char        tolower(char c) const;
  const char* tolower(char* low, const char* high) const;

  Returns:
    do_tolower(c) or do_tolower(low,high)

  char  widen(char c) const;
  const char* widen(const char* low, const char* high,
      char* to) const;

  Effects:
    ::memcpy(to, low, high-low)
  Returns:
    c or hi

  char        narrow(char c, char /*dfault*/) const;
  const char* narrow(const char* low, const char* high,
                     char /*dfault*/, char* to) const;

  Effects:
    ::memcpy(to, low, high-low)
  Returns:
    c or high.

  const mask* table() const throw();

  Returns:
    The first constructor argument, if it was non-zero, otherwise  clas­
    sic_table().

  22.2.1.3.3  ctype<char> static          [lib.facet.ctype.char.statics]
       members

  static const mask* classic_table() throw();

  Returns:
    A   pointer   the   initial   element   of   an   array   of    size
    numeric_limits<unsigned  char>::max() + 1 which represents the clas­
    sifications of characters in the "C" locale.

  22.2.1.3.4  ctype<char> virtual        [lib.facet.ctype.char.virtuals]
       functions

  char        do_toupper(char) const;
  const char* do_toupper(char* low, const char* high) const;
  char        do_tolower(char) const;
  const char* do_tolower(char* low, const char* high) const;

  These functions are described identically as those members of the same
  name in the ctype class template (_lib.locale.ctype.members_).

  22.2.1.4  Class                      [lib.locale.ctype.byname.special]
       ctype_byname<char>
    class ctype_byname<char> : public ctype<charT> {
    public:
      explicit ctype_byname(const char*, size_t refs = 0);
    protected:
     ~ctype_byname();  // virtual
      virtual char        do_toupper(char) const;
      virtual const char* do_toupper(char* low, const char* high) const;
      virtual char        do_tolower(char) const;
      virtual const char* do_tolower(char* low, const char* high) const;
    };
  }

1
  22.2.1.5  Template class codecvt                  [lib.locale.codecvt]
  namespace std {
    class codecvt_base {
    public:
      enum result { ok, partial, error, noconv };
    };
    template <class fromT, class toT, class stateT>
    class codecvt : public locale::facet, public codecvt_base {
    public:
      typedef fromT  from_type;
      typedef toT    to_type;
      typedef stateT state_type;
      explicit codecvt(size_t refs = 0)

      result convert(stateT& state,
          const fromT* from, const fromT* from_end, const fromT*& from_next,
                toT*   to,         toT*   to_limit,         toT*& to_next) const;
      bool always_noconv() const throw();
      int length(const stateT&, const fromT* from, const fromT* end,
                 size_t max) const;
      int max_length() const throw();
      static locale::id id;
    protected:
     ~codecvt();  // virtual
      virtual result do_convert(stateT& state,
          const fromT* from, const fromT* from_end, const fromT*& from_next,
                toT*   to,   toT*         to_limit,       toT*&   to_next) const;
      virtual bool do_always_noconv() const throw();
      virtual int do_length(const stateT&, const fromT* from, const fromT* end,
                            size_t max) const;
      virtual int do_max_length() const throw();
    };
  }

1 The  class  codecvt<fromT,toT,stateT>  is for use when converting from
  one codeset to another, such as  from  wide  characters  to  multibyte
  characters,  or  between  wide character sets such as Unicode and EUC.
  Instances of this facet are typically used in pairs instantiated oppo­
  sitely.

2 The stateT argument selects the pair of codesets being mapped between.

3 Implementations   are   required   to   provide   instantiations   for
  <char,wchar_t,mbstate_t>,         <wchar_t,char,mbstate_t>,        and
  <char,char,mbstate_t>.  The last implements a  degenerate  conversion:
  its  member  always_noconv()  returns true and max_length() returns 1.
  Instantiations on mbstate_t perform conversion between encodings known
  to  the library implementor.  Other encodings can be converted by spe­
  cializing on a user-defined stateT type.  The stateT object  can  con­
  tain  any  state that is useful to communicate to or from the special­
  ized do_convert member.  The base class  implementations  convert  the
  implementation-defined native execution codeset.

  22.2.1.5.1  codecvt members               [lib.locale.codecvt.members]

  result convert(stateT& state,
    const fromT* from, const fromT* from_end, const fromT*& from_next,
            toT* to, toT* to_limit, toT*& to_next) const;

  Returns:
    do_convert(state, from,from_end,from_next, to,to_limit,to_next);

  bool always_noconv() const throw();

  Returns:
    do_always_noconv();

  int length(stateT& state, const fromT* from, const fromT* from_end,
             size_t max) const;

  Returns:
    do_length(state, from,from_end,max);

  +-------                 BEGIN BOX 6                -------+
  Change:  Removed  throw() from the declaration of length() for consis­
  tency with member convert().
  +-------                  END BOX 6                 -------+

  int max_length() const throw();

  Returns:
    do_max_length();

  22.2.1.5.2  codecvt virtual              [lib.locale.codecvt.virtuals]
       functions

  result do_convert(stateT& state,
    const fromT* from, const fromT* from_end, const fromT*& from_next,
            toT* to, toT* to_limit, toT*& to_next) const;

  Preconditions:
    (from<=from_end && to<=to_end) well-defined and true; state initial­
    ized, if at the beginning of a sequence, or else equal to the result
    of converting the preceding characters in the sequence.
  Effects:
    Translates  characters  in  the  range  [from,from_end), placing the
    results in sequential positions starting at to.   Converts  no  more
    than  (from_end-from)  fromT  elements,  and  stores  no  more  than
    (to_limit-to) toT elements.
    Stops if it encounters a character it  cannot  convert.   It  always
    leaves  the  from_next  and to_next pointers pointing one beyond the
    last character successfully converted.  [Note: If no translation  is
    needed  (returns  noconv),  sets  to_next  equal to argument to, and
    from_next equal to argument from.   --end note]
  Notes:
    Its operations on state are unspecified.
    [Note: This argument can be used, for  example,  to  maintain  shift
    state,  to  specify  conversion  options (such as count only), or to
    identify a cache of seek offsets.   --end note]
  Returns:
    An enumeration value, as summarized in Table 4:

                       Table 4--convert result values

     +-----------------------------------------------------------------+
     | Value                           Meaning                         |
     +-----------------------------------------------------------------+
     |ok        completed the conversion                               |
     |partial   not all source characters converted                    |
     |error     encountered a from_type character it could not convert |
     |noconv    no conversion was needed                               |
     +-----------------------------------------------------------------+
    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.

  bool do_always_noconv() const throw();

  Returns:
    true  if  do_convert() returns noconv for all valid argument values.
    The   base    class    implementation    for    the    instantiation
    <char,char,mbstate_t> returns true, others return false.

  +-------                 BEGIN BOX 7                -------+
  Change:  Clarified  that  the  base  class  implementation of only the
  <char,char,mbstate_t> instantiation returns true;  it  would  make  no
  sense  for  the others to return true because they have actual conver­
  sion work to do.
  +-------                  END BOX 7                 -------+

  int do_length(stateT& state, const fromT* from, const fromT* from_end,
                size_t max) const;

  Preconditions:
    (from<=from_end) well-defined and true; state initialized, if at the
    beginning  of  a sequence, or else equal to the result of converting
    the preceding characters in the sequence.
  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 fromT.  The base class implementation returns the lesser of
    max and (from_end-from).

  int do_max_length() const throw();

  Returns:
    The maximum value that do_length(state,from,from_end,1)  can  return
    for any valid range [from,from_end) and stateT value state.

  22.2.1.6  Template class                   [lib.locale.codecvt.byname]
       codecvt_byname
  namespace std {
    template <class fromT, class toT, class stateT>
    class codecvt_byname : public codecvt<fromT, toT, stateT> {
    public:
      explicit codecvt_byname(const char*, size_t refs = 0);
    protected:
     ~codecvt_byname();  // virtual
      virtual result do_convert(stateT& state,
        const fromT* from, const fromT* from_end, const fromT*& from_next,
              toT*   to,   toT*         to_limit,       toT*&   to_next) const;
      virtual bool do_always_noconv() const throw();
      virtual int do_length(const stateT&, const fromT* from, const fromT* end,
                            size_t max) const;
      virtual int do_max_length() const throw();
    };
  }

  22.2.2  The numeric category                    [lib.category.numeric]

1 The classes num_get<> and  num_put<>  handle  numeric  formatting  and
  parsing.   Virtual  functions  are provided for several numeric types.
  Implementations may (but are not required to) delegate  extraction  of
  smaller types to extractors for larger types.7)

2 The  base  class  implementation  refers to the ios_base& argument for
  formatting specifications (_lib.locale.categories_), and to its imbued
  locale  for  the  numpunct<> facet to identify all numeric punctuation
  preferences, and also for the ctype<> facet to perform character clas­
  sification.

3 Extractor and inserter members of the standard iostreams use num_get<>
  and num_put<> member functions for formatting and parsing numeric val­
  ues  (_lib.istream.formatted.reqmts_, _lib.ostream.formatted.reqmts_).

  22.2.2.1  Template class num_get                  [lib.locale.num.get]
  namespace std {
    template <class charT, class InputIterator = istreambuf_iterator<charT> >
    class num_get : public locale::facet {
    public:
      typedef charT            char_type;
      typedef InputIterator    iter_type;
      explicit num_get(size_t refs = 0);
  _________________________
  7)  Parsing "-1" correctly into (e.g.) an unsigned short requires that
  the corresponding member get() at least extract the sign before  dele­
  gating.

      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, bool& v)          const;
      iter_type get(iter_type in, iter_type end, ios_base& ,
                    ios_base::iostate& err, long& v)          const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, unsigned short& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, unsigned int& v)  const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, unsigned long& v) const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, float& v)         const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, double& v)        const;
      iter_type get(iter_type in, iter_type end, ios_base&,
                    ios_base::iostate& err, long double& v)   const;
      static locale::id id;
    protected:
     ~num_get();  // virtual
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, bool& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, long& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, unsigned short& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, unsigned int& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, unsigned long& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, float& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, double& v) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, long double& v) const;
    };
  }

1 The facet num_get is used  to  parse  numeric  values  from  an  input
  sequence such as an istream.

  22.2.2.1.1  num_get members                [lib.facet.num.get.members]

  iter_type get(iter_type in, iter_type end, ios_base& str,
                ios_base::iostate& err, bool& val) const;
  iter_type get(iter_type in, iter_type end, ios_base& str,
                ios_base::iostate& err, long& val) const;
  iter_type get(iter_type in, iter_type end, ios_base& str,
                ios_base::iostate& err, unsigned short& val) const;
  iter_type get(iter_type in, iter_type end, ios_base& str,
                ios_base::iostate& err, unsigned int& val) const;
  iter_type get(iter_type in, iter_type end, ios_base& str,
                ios_base::iostate& err, unsigned long& val) const;
  iter_type get(iter_type in, iter_type end, ios_base& str,
                ios_base::iostate& err, short& val) const;
  iter_type get(iter_type in, iter_type end, ios_base& str,
                ios_base::iostate& err, double& val) const;
  iter_type get(iter_type in, iter_type end, ios_base& str,
                ios_base::iostate& err, long double& val) const;

  Returns:
    do_get(in, end, str, err, val).

  22.2.2.1.2  num_get virtual               [lib.facet.num.get.virtuals]
       functions

  iter_type do_get(iter_type in, iter_type end, ios_base& str,
                   ios_base::iostate& err, bool& val) const;
  iter_type do_get(iter_type in, iter_type end, ios_base& str,
                   ios_base::iostate& err, long& val) const;
  iter_type do_get(iter_type in, iter_type end, ios_base& str,
                   ios_base::iostate& err, unsigned short& val) const;
  iter_type do_get(iter_type in, iter_type end, ios_base& str,
                   ios_base::iostate& err, unsigned int& val) const;
  iter_type do_get(iter_type in, iter_type end, ios_base& str,
                   ios_base::iostate& err, unsigned long& val) const;
  iter_type do_get(iter_type in, iter_type end, ios_base& str,
                   ios_base::iostate& err, float& val) const;
  iter_type do_get(iter_type in, iter_type end, ios_base& str,
                   ios_base::iostate& err, double& val) const;
  iter_type do_get(iter_type in, iter_type end, ios_base& str,
                   ios_base::iostate& err, long double& val) const;

  Effects:
    Reads  characters  from   in,   interpreting   them   according   to
    str.flags(),   use_facet<   ctype<charT>   >(loc),   and  use_facet<
    numpunct<charT> >(loc).  If an error occurs, val is unchanged;  oth­
    erwise it is set to the resulting value.
    Digit  group  separators are optional; if present, digit grouping is
    checked after the entire number is read.  If no grouping  is  speci­
    fied,  any  thousands  separator characters encountered in the input
    sequence are not considered part of the numeric format.
    When reading a non-numeric boolean value,  the  names  are  compared
    exactly.

  Returns:
    An iterator pointing one past the last character consumed as part of
    the converted field.

  22.2.2.2  Template class num_put                  [lib.locale.num.put]
  namespace std {
    template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
    class num_put : public locale::facet {
    public:
      typedef charT            char_type;
      typedef OutputIterator   iter_type;
      explicit num_put(size_t refs = 0);
      iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill, long v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill,
                    unsigned long v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill,
                    double v) const;
      iter_type put(iter_type s, ios_base& f, char_type fill,
                    long double v) const;
      static locale::id id;
    protected:
     ~num_put();  // virtual
      virtual iter_type do_put(iter_type, ios_base&, char_type fill,
                               bool v) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill,
                               long v) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill,
                               unsigned long) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill,
                               double v) const;
      virtual iter_type do_put(iter_type, ios_base&, char_type fill,
                               long double v) const;
    };
  }

1 The facet num_put is used to format  numeric  values  to  a  character
  sequence such as an ostream.

  22.2.2.2.1  num_put members                [lib.facet.num.put.members]

  iter_type put(iter_type out, ios_base& str, char_type fill,
                bool val) const;
  iter_type put(iter_type out, ios_base& str, char_type fill,
                long val) const;
  iter_type put(iter_type out, ios_base& str, char_type fill,
                unsigned long val) const;
  iter_type put(iter_type out, ios_base& str, char_type fill,
                double val) const;
  iter_type put(iter_type out, ios_base& str, char_type fill,
                long double val) const;

  Returns:
    do_put(out, str, fill, val).

  22.2.2.2.2  num_put virtual               [lib.facet.num.put.virtuals]
       functions

  iter_type do_put(iter_type out, ios_base& str, char_type fill,
                   bool val) const;
  iter_type do_put(iter_type out, ios_base& str, char_type fill,
                   long val) const;
  iter_type do_put(iter_type out, ios_base& str, char_type fill,
                   unsigned long val) const;
  iter_type do_put(iter_type out, ios_base& str, char_type fill,
                   double val) const;
  iter_type do_put(iter_type out, ios_base& str, char_type fill,
                   long double val) const;

  Effects:
    Writes characters to the sequence out, formatting val  according  to
    str.flags(),  fill,  use_facet<  ctype<charT>  >(str.getloc()),  and
    use_facet< numpunct<charT>  >(str.getloc()).   Inserts  digit  group
    separators as specified by numpunct<charT>::do_grouping.
  Returns:
    An  iterator pointing immediately after the last character produced.

  22.2.3  The numeric punctuation facet             [lib.facet.numpunct]

  22.2.3.1  Template class numpunct                [lib.locale.numpunct]
  namespace std {
    template <class charT>
    class numpunct : public locale::facet {
    public:
      typedef charT               char_type;
      typedef basic_string<charT> string_type;
      explicit numpunct(size_t refs = 0);
      char_type    decimal_point()   const;
      char_type    thousands_sep()   const;
      string       grouping()        const;
      string_type  truename()        const;
      string_type  falsename()       const;
      static locale::id id;
    protected:
     ~numpunct();  // virtual
      virtual char_type    do_decimal_point() const;
      virtual char_type    do_thousands_sep() const;
      virtual string       do_grouping()      const;
      virtual string_type  do_truename()      const;  // for bool
      virtual string_type  do_falsename()     const;  // for bool
    };
  }

1 numpunct<> specifies numeric punctuation.   The  base  class  provides
  classic  C" numeric formats, while the _byname" version supports named
  locale (e.g. POSIX, X/Open) numeric formatting semantics.

2 The syntax for number formats is as follows,  where  digit  represents
  the  radix set specified by the fmtflags argument value, whitespace is
  as determined by  the  facet  ctype<charT>  (_lib.locale.ctype_),  and
  thousands-sep  and  decimal-point  are  the  results  of corresponding
  numpunct<charT> members.  Integer values have the format:
    integer   ::= [sign] units
    sign      ::= plusminus [whitespace]
    plusminus ::= '+' | '-'
    units     ::= digits [thousands-sep units]
    digits    ::= digit [digits]
  and floating-point values have:
    floatval ::= [sign] units [decimal-point [digits]] [e [sign] digits] |
                 [sign]        decimal-point  digits   [e [sign] digits]
    e        ::= 'e' | 'E'
  where the number of digits between thousands-seps is as  specified  by
  do_grouping().   For  parsing, if the digits portion contains no thou­
  sands-separators, no grouping constraint is applied.

  +-------                 BEGIN BOX 8                -------+
  Note: The WG agreed that sequences such as "0xFF" are  valid  numbers,
  and (editorially) need to be represented in the syntax spec above.
  +-------                  END BOX 8                 -------+

  22.2.3.1.1  numpunct members              [lib.facet.numpunct.members]

  char_type decimal_point() const;

  Returns:
    do_decimal_point()

  char_type thousands_sep() const;

  Returns:
    do_thousands_sep()

  +-------                 BEGIN BOX 9                -------+
  Change:  The  previous  version  said  thousands_sep()  returned thou­
  sands_sep() (itself).  Changed to do_thousands_sep().
  +-------                  END BOX 9                 -------+

  string grouping()  const;

  Returns:
    do_grouping()

  string_type truename()  const;
  string_type falsename() const;

  Returns:
    do_truename() or do_falsename(), respectively.

  22.2.3.1.2  numpunct virtual             [lib.facet.numpunct.virtuals]
       functions

  char_type do_decimal_point() const;

  Returns:
    A  character for use as the decimal radix separator.  The base class
    implementation returns '.'.

  string_type do_thousands_sep() const;

  Returns:
    A character for use as the digit group separator.   The  base  class
    implementation returns ','.

  string do_grouping() const;

  Returns:
    A  basic_string<char>  vec  used  as  a vector of integer values, in
    which  each  element vec[i] represents the number of digits8) in the
    group at position i, starting  with  position  0  as  the  rightmost
    group.   If  vec.size() <= i, the number is the same as group (i-1);
    if (i<0 || vec[i]<=0 || vec[i]==CHAR_MAX), the  size  of  the  digit
    group is unlimited.
    The  base  class implementation returns the empty string, indicating
    no grouping.

  string_type do_truename()  const;
  string_type do_falsename() const;

  Returns:
    A string representing the name of the boolean value true  or  false,
    respectively.
    In the base class implementation these names are "true" and "false".

  _________________________
  8) Thus, the string " 03" specifies groups of 3 digits each,  and  "3"
  probably indicates groups of 51 (!) digits each.

  22.2.3.2  Template class                  [lib.locale.numpunct.byname]
       numpunct_byname
  namespace std {
    template <class charT>
    class numpunct_byname : public numpunct<charT> {
      // this class is specialized for char and wchar_t.
    public:
      explicit numpunct_byname(const char*, size_t refs = 0);
    protected:
     ~numpunct_byname();  // virtual
      virtual char_type    do_decimal_point() const;
      virtual char_type    do_thousands_sep() const;
      virtual string       do_grouping()      const;
      virtual string_type  do_truename()      const;  // for bool
      virtual string_type  do_falsename()     const;  // for bool
    };
  }

  22.2.4  The collate category                    [lib.category.collate]

  22.2.4.1  Template class collate                  [lib.locale.collate]
  namespace std {
    template <class charT>
    class collate : public locale::facet {
    public:
      typedef charT               char_type;
      typedef basic_string<charT> string_type;
      explicit collate(size_t refs = 0);
      int compare(const charT* low1, const charT* high1,
                  const charT* low2, const charT* high2) const;
      string_type transform(const charT* low, const charT* high) const;
      long hash(const charT* low, const charT* high) const;
      static locale::id id;
    protected:
     ~collate();  // virtual
      virtual int    do_compare(const charT* low1, const charT* high1,
                                const charT* low2, const charT* high2) const;
      virtual string_type do_transform(const charT* low, const charT* high) const;
      virtual long   do_hash     (const charT* low, const charT* high) const;
    };
  }

1 The  class  collate<charT>  provides features for use in the collation
  (comparison) and hashing of strings.  A locale  member  function  tem­
  plate,  operator(),  uses  the  collate facet to allow a locale to act
  directly  as  the   predicate   argument   for   standard   algorithms
  (_lib.algorithms_)  and  containers  operating  on  strings.  The base
  class     implementation      applies      lexicographic      ordering
  (_lib.alg.lex.comparison_).

2 Each  function  compares  a  string  of  characters  *p  in  the range
  [low,high).

  22.2.4.1.1  collate members               [lib.locale.collate.members]

  int compare(const charT* low1, const charT* high1,
              const charT* low2, const charT* high2) const;

  Returns:
    do_compare(low1, high1, low2, high2)

  string_type transform(const charT* low, const charT* high) const;

  Returns:
    do_transform(low, high)

  long hash(const charT* low, const charT* high) const;

  Returns:
    do_hash(low, high)

  22.2.4.1.2  collate virtual              [lib.locale.collate.virtuals]
       functions

  int do_compare(const charT* low1, const charT* high1,
                 const charT* low2, const charT* high2) const;

  Returns:
    1  if  the first string is greater than the second, -1 if less, zero
    otherwise.  The base class implementation implements a lexicographi­
    cal comparison (_lib.alg.lex.comparison_).

  string_type do_transform(const charT* low, const charT* high) const;

  Returns:
    A  basic_string<charT>  value  that, compared lexicographically with
    the result of calling transform() on another string, yields the same
    result as calling do_compare() on the same two strings.9)

  long do_hash(const charT* low, const charT* high) const;

  Returns:
    An integer value equal to the result of calling hash() on any  other
    string  for which do_compare() returns 0 (equal) when passed the two
    strings.  [Note: The probability that the  result  equals  that  for
    another  string  which  does not compare equal should be very small,
  _________________________
  9)  This  function is useful when one string is being compared to many
  other strings.

    approaching  (1.0/numeric_limits<unsigned  long>::max()).      --end
    note]

  22.2.4.2  Template class                   [lib.locale.collate.byname]
       collate_byname
  namespace std {
    template <class charT>
    class collate_byname : public collate<charT> {
    public:
      explicit collate_byname(const char*, size_t refs = 0);
    protected:
     ~collate_byname();  // virtual
      virtual int    do_compare(const charT* low1, const charT* high1,
                                const charT* low2, const charT* high2) const;
      virtual string_type do_transform(const charT* low, const charT* high) const;
      virtual long   do_hash(     const charT* low, const charT* high) const;
    };

  22.2.5  The time category                          [lib.category.time]

1 The        templates         time_get<charT,InputIterator>         and
  time_put<charT,OutputIterator>  provide  date  and time formatting and
  parsing.  Their members use their ios_base&,  ios_base::iostate&,  and
  fill  arguments  as  described  in  (_lib.locale.categories_), and the
  ctype<> facet, to determine formatting details.

  22.2.5.1  Template class time_get                [lib.locale.time.get]
  namespace std {
    class time_base {
    public:
      enum dateorder { no_order, dmy, mdy, ymd, ydm };
    };

    template <class charT, class InputIterator = istreambuf_iterator<charT> >
    class time_get : public locale::facet, public time_base {
    public:
      typedef charT            char_type;
      typedef InputIterator    iter_type;
      explicit time_get(size_t refs = 0);
      dateorder date_order()  const { return do_date_order(); }
      iter_type get_time(iter_type s, iter_type end, ios_base& f,
                         ios_base::iostate& err, tm* t)  const;
      iter_type get_date(iter_type s, iter_type end, ios_base& f,
                         ios_base::iostate& err, tm* t)  const;
      iter_type get_weekday(iter_type s, iter_type end, ios_base& f,
                            ios_base::iostate& err, tm* t) const;
      iter_type get_monthname(iter_type s, iter_type end, ios_base& f,
                              ios_base::iostate& err, tm* t) const;
      iter_type get_year(iter_type s, iter_type end, ios_base& f,
                         ios_base::iostate& err, tm* t\fP) const;
      static locale::id id;

    protected:
     ~time_get();  // virtual
      virtual dateorder do_date_order()  const;
      virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&,
                                    ios_base::iostate& err, tm* t) const;
      virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&,
                                    ios_base::iostate& err, tm* t) const;
      virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&,
                                       ios_base::iostate& err, tm* t) const;
      virtual iter_type do_get_monthname(iter_type s, ios_base&,
                                         ios_base::iostate& err, tm* t) const;
      virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&,
                                    ios_base::iostate& err, tm* t) const;
    };
  }

1 time_get is used to parse a character sequence, extracting  components
  of  a  time or date into a struct tm record.  Each get member parses a
  format  as  produced  by   a   corresponding   format   specifier   to
  time_put<>::put.   If  the  sequence  being parsed matches the correct
  format, the corresponding members of the struct tm argument are set to
  the  values used to produce the sequence; otherwise either an error is
  reported or unspecified values are assigned.10)

  22.2.5.1.1  time_get members             [lib.locale.time.get.members]

  dateorder date_order() const;

  Returns:
    do_date_order()

  iter_type get_time(iter_type s, iter_type end, ios_base& str,
                     ios_base::iostate& err, tm* t) const;

  Returns:
    do_get_time(s, end, str, err, t)

  iter_type get_date(iter_type s, iter_type end, ios_base& str,
                     ios_base::iostate& err, tm* t) const;

  Returns:
    do_get_date(s, end, str, err, t)

  _________________________
  10) In other words, user confirmation is required for reliable parsing
  of  user-entered dates and times, but machine-generated formats can be
  parsed reliably.  This allows parsers to be  aggressive  about  inter­
  preting user variations on standard formats.

  iter_type get_weekday(iter_type s, iter_type end, ios_base& str,
                        ios_base::iostate& err, tm* t) const;
  iter_type get_monthname(iter_type s, iter_type end, ios_base& str,
                          ios_base::iostate& err, tm* t) const;

  Returns:
    do_get_weekday(s, end, str, err, t) or do_get_monthname(s, end, str,
    err, t

  iter_type get_year(iter_type s, iter_type end, ios_base& str,
                     ios_base::iostate& err, tm* t) const;

  Returns:
    do_get_year(s, end, str, err, t)

  22.2.5.1.2  time_get virtual            [lib.locale.time.get.virtuals]
       functions

  dateorder do_date_order() const;

  Returns:
    An  enumeration  value  indicating the preferred order of components
    for those date formats that are composed of day, month, and year.11)
    Returns no_order if the date format specified by 'x' contains  other
    variable components (e.g. Julian day, week number, week day).

  +-------                BEGIN BOX 10                -------+
  Change:  Changed X to x above; the C strftime format %X does not spec­
  ify any date components.
  +-------                 END BOX 10                 -------+

  iter_type do_get_time(iter_type s, iter_type end, ios_base& str,
                        ios_base::iostate& err, tm* t) const;

  Effects:
    Reads characters starting at s until it has extracted  those  struct
    tm members, and remaining format characters, used by time_put<>::put
    to produce the format specified by 'X', or until  it  encounters  an
    error or end of sequence.
  Returns:
    An  iterator  pointing  immediately beyond the last character recog­
    nized as possibly part of a valid time.

  _________________________
  11)  This  function is intended as a convenience only, for common for­
  mats, and may return no_order in valid locales.

  iter_type do_get_date(iter_type s, iter_type end, ios_base& str,
                        ios_base::iostate& err, tm* t) const;

  Effects:
    Reads characters starting at s until it has extracted  those  struct
    tm members, and remaining format characters, used by time_put<>::put
    to produce the format specified by 'x', or until  it  encounters  an
    error.
  Returns:
    An  iterator  pointing  immediately beyond the last character recog­
    nized as possibly part of a valid date.

  iter_type do_get_weekday(iter_type s, iter_type end, ios_base& str,
                           ios_base::iostate& err, tm* t) const;
  iter_type do_get_monthname(iter_type s, iter_type end, ios_base& str,
                             ios_base::iostate& err, tm* t) const;

  Effects:
    Reads characters starting at s until it has extracted  the  (perhaps
    abbreviated)  name  of a weekday or month.  If it finds an abbrevia­
    tion that is followed by characters that could match a full name, it
    continues  reading until it matches the full name or fails.  It sets
    the appropriate struct tm member accordingly.
  Returns:
    An iterator pointing immediately beyond the  last  character  recog­
    nized as part of a valid name.

  iter_type do_get_year(iter_type s, iter_type end, ios_base& str,
                        ios_base::iostate& err, tm* t) const;

  Effects:
    Reads characters starting at s until it has extracted an unambiguous
    year identifier.  It  is  implementation-defined  whether  two-digit
    year numbers are accepted, and (if so) what century they are assumed
    to lie in.  Sets the t->tm_year member accordingly.
  Returns:
    An iterator pointing immediately beyond the  last  character  recog­
    nized as part of a valid year identifier.

  22.2.5.2  Template class                  [lib.locale.time.get.byname]
       time_get_byname

  namespace std {
    template <class charT, class InputIterator = istreambuf_iterator<charT> >
    class time_get_byname : public time_get<charT, InputIterator> {
    public:
      explicit time_get_byname(const char*, size_t refs = 0);
    protected:
     ~time_get_byname();  // virtual
      virtual dateorder do_date_order()  const;
      virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&,
                                    ios_base::iostate& err, tm* t) const;
      virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&,
                                    ios_base::iostate& err, tm* t) const;
      virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&,
                                       ios_base::iostate& err, tm* t) const;
      virtual iter_type do_get_monthname(iter_type s, iter_type end, ios_base&,
                                         ios_base::iostate& err, tm* t) const;
      virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&,
                                    ios_base::iostate& err, tm* t) const;
    };
  }

  22.2.5.3  Template class time_put                [lib.locale.time.put]
  namespace std {
    template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
    class time_put : public locale::facet {
    public:
      typedef charT            char_type;
      typedef OutputIterator   iter_type;
      explicit time_put(size_t refs = 0);
        // the following is implemented in terms of other member functions.
      iter_type put(iter_type s, ios_base& f, char_type fill, const tm* tmb,
                    const charT* pattern, const charT* pat_end) const;
      iter_type put(iter_type s, ios_base& f, char_type fill,
                    const tm* tmb, char format, char modifier = 0) const;
      static locale::id id;
    protected:
     ~time_put();  // virtual
      virtual iter_type do_put(iter_type s, ios_base&, char_type, const tm* t,
                               char format, char modifier) const;
    };
  }

  22.2.5.3.1  time_put members             [lib.locale.time.put.members]

  iter_type put(iter_type s, ios_base&, char_type fill, const tm* t,
                const charT* pattern, const charT* pat_end) const;
  iter_type put(iter_type s, ios_base&, char_type fill, const tm* t,
                char format, char modifier = 0) const;

  Effects:
    The first form interprets the characters immediately following  a  %
    in  the  sequence  between pattern and pat_end as format specifiers,

    according to the mapping used by the function strftime()  Characters
    are converted using ctype<>::narrow() to identify format specifiers.
    [Note: This implies that if narrow() has no mapping for the  charac­
    ter %, no format specifiers are identified.   --end note]
    The  second form calls do_put() once, simply passing along its argu­
    ments.
  Returns:
    An iterator pointing immediately after the last character  produced.

  22.2.5.3.2  time_put virtual            [lib.locale.time.put.virtuals]
       functions

  iter_type do_put(iter_type s, ios_base&, char_type fill, const tm* t,
                   char format, char modifier) const;

  Effects:
    Formats the contents of the parameter t into  characters  placed  on
    the  output  sequence s.  Formatting is controlled by the parameters
    format and modifier, interpreted identically as  the  format  speci­
    fiers  in  the  string  argument  to  the  standard library function
    strftime().12)
  Returns:
    An  iterator pointing immediately after the last character produced.

  22.2.5.4  Template class                  [lib.locale.time.put.byname]
       time_put_byname
  namespace std {
    template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
    class time_put_byname : public time_put<charT, OutputIterator>
    {
    public:
      explicit time_put_byname(const char*, size_t refs = 0);
    protected:
     ~time_put_byname();  // virtual
      virtual iter_type do_put(iter_type s, ios_base&, char_type, const tm* t,
                               char format, char modifier) const;
    };
  }

  22.2.6  The monetary category                  [lib.category.monetary]

1 These  templates  handle monetary formats.  A template parameter indi­
  cates whether local or international monetary formats are to be  used.

2 money_get<>    and    money_put<>   members   use   their   ios_base&,
  ios_base::iostate&,   and   fill    arguments    as    described    in
  (_lib.locale.categories_), and the moneypunct<> and ctype<> facets, to
  determine formatting details.
  _________________________
  12) Interpretation of the modifier argument is implementation-defined,
  but should follow POSIX conventions.

  22.2.6.1  Template class money_get              [lib.locale.money.get]
  namespace std {
    template <class charT, bool Intl = false,
              class InputIterator = istreambuf_iterator<charT> >
    class money_get : public locale::facet {
    public:
      typedef charT               char_type;
      typedef InputIterator       iter_type;
      typedef basic_string<charT> string_type;
      explicit money_get(size_t refs = 0);
      iter_type get(iter_type s, iter_type end, ios_base& f,
                    ios_base::iostate& err, long double& units) const;
      iter_type get(iter_type s, iter_type end, ios_base& f,
                    ios_base::iostate& err, string_type& digits) const;
      static const bool intl = Intl;
      static locale::id id;
    protected:
     ~money_get();  // virtual
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, long double& units) const;
      virtual iter_type do_get(iter_type, iter_type, ios_base&,
                               ios_base::iostate& err, string_type& digits) const;
    };
  }

  22.2.6.1.1  money_get members           [lib.locale.money.get.members]

  iter_type get(iter_type s, iter_type end, ios_base& f,
                ios_base::iostate& err, long double& quant) const;
  iter_type get(s, iter_type end, ios_base&f,
                ios_base::iostate& err, string_type& quant) const;

  Returns:
    do_get(s, end, f, err, quant)

  22.2.6.1.2  money_get virtual          [lib.locale.money.get.virtuals]
       functions

  iter_type do_get(iter_type s, iter_type end, ios_base& str,
                   ios_base::iostate& err, long double& units) const;
  iter_type do_get(iter_type s, iter_type end, ios_base& strfP,
                   ios_base::iostate& err, string_type& digits) const;

  Effects:
    Reads  characters  from s until it has constructed a monetary value,
    as specified in  str.flags()  and  the  moneypunct<charT>  facet  of
    str.getloc(), or until it encounters an error or runs out of charac­
    ters.   It  parses  the  format   sequence   specified   by   money­
    punct<>::neg_format() for all monetary values.  The result is a pure
    sequence of digits, representing a count of  the  smallest  unit  of
    currency representable.13)
  _________________________
  13) For  example, the sequence $1,056.23 in a common U.S. locale would

    Digit group separators are optional; if present, digit  grouping  is
    checked after all syntactic elements have been read.  If no grouping
    is specified, any thousands separator characters encountered in  the
    input sequence are not considered part of the numeric format.
    Where space or none appear in the format pattern, except at the end,
    optional   whitespace    is    consumed.     If    (str.flags()    &
    ios_base::showbase)  is  false, the currency symbol is optional, and
    if it appears after all other required syntactic elements it is  not
    consumed.   If  the expression above is true, the currency symbol is
    required, and is always consumed.  If the first character of  the  a
    sign  appears in its correct position, any remaining sign characters
    are required, and consumed.  [Example: If showbase is off, then when
    the  sign  is  "()" and the currency symbol is "L", in "(100 L)" the
    "L" is consumed; but in "-100 L" it is not.    --end  example]  Sets
    the  argument  units  or  digits  from the sequence of digits found.
    units is negated, or digits is  preceded  by  '-',  for  a  negative
    value.  On error, the units or digits argument is unchanged.
  Returns:
    An  iterator  pointing  immediately beyond the last character recog­
    nized as part of a valid monetary quantity.

  +-------                BEGIN BOX 11                -------+
  The description above needs further review.
  +-------                 END BOX 11                 -------+

  22.2.6.2  Template class money_put              [lib.locale.money.put]
  namespace std {
    template <class charT, bool Intl = false,
              class OutputIterator = ostreambuf_iterator<charT> >
    class money_put : public locale::facet {
    public:
      typedef charT               char_type;
      typedef OutputIterator      iter_type;
      typedef basic_string<charT> string_type;
      explicit money_put(size_t refs = 0);
      iter_type put(iter_type s, ios_base& f, char_type fill,
                    long double units) const;
      iter_type put(iter_type s, ios_base& f, char_type fill,
                    const string_type& digits) const;
      static const bool intl = Intl;
      static locale::id id;

  _________________________
  yield, for units, 105623, or for digits, 105623".

    protected:
     ~money_put();  // virtual
      virtual iter_type
        do_put(iter_type, ios_base&, char_type fill, long double units) const;
      virtual iter_type
        do_put(iter_type, ios_base&, char_type fill,
               const string_type& digits) const;
    };
  }

  22.2.6.2.1  money_put members           [lib.locale.money.put.members]

  iter_type put(iter_type s, ios_base& f, char_type fill,
                long double quant) const;
  iter_type put(iter_type s, ios_base& f, char_type fill,
                const string_type& quant) const;

  Returns:
    do_put(s, f, loc, quant)

  22.2.6.2.2  money_put virtual          [lib.locale.money.put.virtuals]
       functions

  iter_type do_put(iter_type s, ios_base& str, char_type fill,
                   long double units) const;
  iter_type do_put(iter_type s, ios_base& str, char_type fill,
                   const string_type& digits) const;

  Effects:
    Writes  characters  to  s,  according to the format specified by the
    moneypunct<charT> facet of loc, and str.flags().  Ignores any  frac­
    tional  part  of  units,  or  any  characters  in  digits beyond the
    (optional) leading '-' and immediately subsequent digits.
  Notes:
    The  currency  symbol  is   generated   only   if   (str.flags()   &
    ios_type::showbase)     is     true.      If     ((str.flags()     &
    ios_type::adjustfield) == ios_type::internal)  the  fill  characters
    are  placed  where  none  or space appears in the formatting pattern
    (_lib.money.get.virtuals_).
  Returns:
    An iterator pointing immediately after the last character  produced.

  22.2.6.3  Template class moneypunct            [lib.locale.moneypunct]

  namespace std {
    class money_base {
    public:
      enum part { none, space, symbol, sign, value };
      struct pattern { char field[4]; };
    };

    template <class charT, bool International = false>
    class moneypunct : public locale::facet, public money_base {
    public:
      typedef charT char_type;
      typedef basic_string<charT> string_type;
      explicit moneypunct(size_t refs = 0);
      charT        decimal_point() const;
      charT        thousands_sep() const;
      string       grouping()      const;
      string_type  curr_symbol()   const;
      string_type  positive_sign() const;
      string_type  negative_sign() const;
      int          frac_digits()   const;
      pattern      pos_format()    const;
      pattern      neg_format()    const;
      static locale::id id;
      static const bool intl = International;
    protected:
     ~moneypunct();  // virtual
      virtual charT        do_decimal_point() const;
      virtual charT        do_thousands_sep() const;
      virtual string       do_grouping()      const;
      virtual string_type  do_curr_symbol()   const;
      virtual string_type  do_positive_sign() const;
      virtual string_type  do_negative_sign() const;
      virtual int          do_frac_digits()   const;
      virtual pattern      do_pos_format()    const;
      virtual pattern      do_neg_format()    const;
    };
  }

1 This   provides   money   punctuation,  similar  to  numpunct<>  above
  (_lib.locale.numpunct_).  In particular, the value portion of the for­
  mat is:
    value ::= units [decimal-point [digits]] |
              decimal-point digits
  if frac_digits returns a positive value, or just
    value ::= units
  otherwise.   In these forms, the decimal-point and thousands-separator
  are as determined below and the number of  digits  after  the  decimal
  point is exactly the value returned by frac_digits.

  22.2.6.3.1  moneypunct members         [lib.locale.moneypunct.members]

      charT        decimal_point() const;
      charT        thousands_sep() const;
      string       grouping()      const;
      string_type  curr_symbol()   const;
      string_type  positive_sign() const;
      string_type  negative_sign() const;
      int          frac_digits()   const;
      pattern      pos_format()    const;
      pattern      neg_format()    const;

1 Each  of  these  functions  F returns the result of calling the corre­
  sponding virtual member function do_F().

  22.2.6.3.2  moneypunct virtual        [lib.locale.moneypunct.virtuals]
       functions

  charT do_decimal_point() const;

  Returns:
    The  radix separator to use in case do_frac_digits() is greater than
    zero.14)

  charT do_thousands_sep() const;

  Returns:
    The digit group separator to use in case do_grouping()  specifies  a
    digit grouping pattern.15)

  string       do_grouping() const;

  Returns:
    A     pattern    defined    identically    as    the    result    of
    numpunct<charT>::do_grouping().16)

  string_type do_curr_symbol() const;

  Returns:
    A string to use as the currency identifier symbol.17)
  _________________________
  14) In common U.S. locales this is '.'.
  15) In common U.S. locales this is ','.
  16) This is most commonly the value " 03" not "3").
  17) For international instantiations (second template parameter  true)
  this  is  always  four  characters  long,  usually three letters and a
  space.

  string_type do_positive_sign() const;
  string_type do_negative_sign() const;

  Returns:
    do_positive_sign() returns the string to use to indicate a  positive
    monetary  value;18)  do_negative_sign() returns the string to use to
    indicate a negative value.  The first character of  the  string  (if
    any)  is placed in the position indicated for the sign in the format
    pattern, and any remaining characters are  placed  after  all  other
    format elements.

  int do_frac_digits() const;

  Returns:
    The number of digits after the decimal radix separator, if any.19)

  pattern do_pos_format() const;
  pattern do_neg_format() const;

  Returns:
    A  pattern,  a four-element array specifying the order in which syn­
    tactic elements appear in the monetary format.  In this  array  each
    enumeration  value  symbol,  sign,  value,  and either space or none
    appears exactly once.  none, if present, is  not  first;  space,  if
    present,  is  neither  first  nor last.  Otherwise, the elements may
    appear in any order.   The  base  class  implementation  returns  an
    object of type pattern initialized to { symbol, sign, none, value };
    this value is also returned for all international instantiations.20)

  22.2.6.4  Template class                [lib.locale.moneypunct.byname]
       moneypunct_byname

  _________________________
  18) This is usually the empty string.
  19) In common U.S. locales, this is 2.
  20)  Note that the international symbol returned by do_curr_sym() usu­
  ally contains a space, itself; for example, "USD ".

  namespace std {
    template <class charT, bool Intl = false>
    class moneypunct_byname : public moneypunct<charT, Intl> {
    public:
      explicit moneypunct_byname(const char*, size_t refs = 0);
    protected:
     ~moneypunct_byname();  // virtual
      virtual charT        do_decimal_point() const;
      virtual charT        do_thousands_sep() const;
      virtual string       do_grouping()      const;
      virtual string_type  do_curr_symbol()   const;
      virtual string_type  do_positive_sign() const;
      virtual string_type  do_negative_sign() const;
      virtual int          do_frac_digits()   const;
      virtual pattern      do_pos_format()    const;
      virtual pattern      do_neg_format()    const;
    };
  }

  22.2.7  The message retrieval category         [lib.category.messages]

1 Class  messages<charT>  implements  retrieval  of strings from message
  catalogs.

  22.2.7.1  Template class messages                [lib.locale.messages]
  namespace std {
    class messages_base {
    public:
      typedef int catalog;
    };

    template <class charT>
    class messages : public locale::facet, public messages_base {
    public:
      typedef charT char_type;
      typedef basic_string<charT> string_type;
      explicit messages(size_t refs = 0);
      catalog open(const basic_string<char>& fn, const locale&) const;
      string_type  get(catalog c, int set, int msgid,
                       const string_type& dfault) const;
      void    close(catalog c) const;
      static locale::id id;
    protected:
     ~messages();  // virtual
      virtual catalog do_open(const basic_string<char>&, const locale&) const;
      virtual string_type  do_get(catalog, int set, int msgid,
                             const string_type& dfault) const;
      virtual void    do_close(catalog) const;
    };
  }

1 Values of type messages_base::catalog usable as arguments  to  members
  get and close can be obtained only by calling member open.

  22.2.7.1.1  messages members             [lib.locale.messages.members]

  catalog open(const basic_string<char>& name, const locale& loc) const;

  Returns:
    do_open(name, loc).

  string_type get(catalog cat, int set, int msgid,
                  const string_type& dfault) const;

  Returns:
    do_get(cat, set, msgid, dfault).

  void  close(catalog cat) const;

  Effects:
    Calls do_close(cat).

  22.2.7.1.2  messages virtual            [lib.locale.messages.virtuals]
       functions

  catalog do_open(const basic_string<char>& name,
                  const locale& loc) const;

  Returns:
    A value that may be passed to get() to retrieve a message, from  the
    message catalog identified by the string name according to an imple­
    mentation-defined mapping.  The result  can  be  used  until  it  is
    passed to close().
    Returns a value less than 0 if no such catalog can be opened.
  Notes:
    The  locale  argument  loc is used for character set code conversion
    when retrieving messages, if needed.

  string_type do_get(catalog cat, int set, int msgid,
                const string_type& dfault) const;

  Requires:
    A catalog cat obtained from open() and not yet closed.
  Returns:
    A message identified by arguments set, msgid, and dfault,  according
    to  an  implementation-defined  mapping.   If no such message can be
    found, returns dfault.

  void do_close(catalog cat) const;

  Requires:
    A catalog cat obtained from open() and not yet closed.
  Effects:
    Releases unspecified resources associated with  cat.
  Notes:
    The limit on such resources, if any, is implementation-defined.

  22.2.7.2  Template class                  [lib.locale.messages.byname]
       messages_byname
  namespace std {
    template <class charT>
    class messages_byname : public messages<charT> {
    public:
      explicit messages_byname(const char*, size_t refs = 0);
    protected:
     ~messages_byname();  // virtual
      virtual catalog do_open(const basic_string<char>&, const locale&) const;
      virtual string_type  do_get(catalog, int set, int msgid,
                             const string_type& dfault) const;
      virtual void    do_close(catalog) const;
    };
  }

  22.2.8  Program-defined facets                   [lib.facets.examples]

1 A C++ program may define facets to be added to a locale and used iden­
  tically as the built-in facets.  To create a new facet interface,  C++
  programs  simply derive from locale::facet a class containing a static
  member: static locale::id id.

2 [Note: The locale member function templates verify its type and  stor­
  age class.   --end note]

3 This initialization/identification system depends only on the initial­
  ization to 0 of static objects, before static constructors are called.
  When  an  instance  of  a  facet  is installed in a locale, the locale
  checks whether an id has been  assigned,  and  if  not,  assigns  one.
  Before  this  occurs,  any  attempted  use of its interface causes the
  bad_cast exception to be thrown.

4 [Example: Here is a program that just calls C functions:
    #include <locale>
    extern "C" void c_function();
    int main()
    {
      using namespace std;
      locale::global(locale(""));  // same as setlocale(LC_ALL, "");
      c_function();
      return 0;
    }
  In other words, C library localization is unaffected.   --end example]

5 [Example: Traditional global localization is still easy:
    #include <iostream>
    #include <locale>
    int main(int argc, char** argv)
    {
      using namespace std;
      locale::global(locale(""));  // set the global locale
       cin.imbue(locale());        // imbue it on the std streams
      cout.imbue(locale());
      cerr.imbue(locale());
      return MyObject(argc, argv).doit();
    }
   --end example]

6 [Example: Greater flexibility is possible:
    #include <iostream>
    #include <locale>
    int main()
    {
      using namespace std;
      cin.imbue(locale(""));  // the user's preferred locale
      cout.imbue(locale::classic());
      double f;
      while (cin >> f) cout << f << endl;
      return (cin.fail() != 0);
    }
  In  a European locale, with input 3.456,78, output is 3456.78.   --end
  example]

7 This can be important even for simple  programs,  which  may  need  to
  write  a  data  file in a fixed format, regardless of a user's prefer­
  ence.

8 [Example: Here is an example of the use of locales in a library inter­
  face.
    // file: Date.h
    #include <iosfwd>
    #include <string>
    #include <locale>
       ...
    class Date {
      ...
     public:
      Date(unsigned day, unsigned month, unsigned year);
      std::string asString(const std::locale& = std::locale());
    };
    istream& operator>>(istream& s, Date& d);
    ostream& operator<<(ostream& s, Date d);
    ...
  This example illustrates two architectural uses of class locale.

9 The  first  is  as  a  default argument in Date::asString(), where the
  default is the global (presumably user-preferred) locale.

10The second is in the operators << and >>, where a locale  "hitchhikes"
  on  another  object,  in  this case a stream, to the point where it is
  needed.
    // file: Date.C
    #include "Date"  // includes <ctime>
    #include <sstream>
    std::string Date::asString(const std::locale& l)
    {
      using namespace std;
      ostringstream s; s.imbue(l);
      s << *this; return s.str();
    }
    std::istream& operator>>(std::istream& s, Date& d)
    {
      using namespace std;
      istream::sentry cerberos;
      if (cerberos) {
        ios_base::iostate err = goodbit;
        struct tm t;
        use_facet< time_get<char> >(s.getloc()).get_date(s, 0, s, err, &t);
        if (!err) d = Date(t.tm_day, t.tm_mon + 1, t.tm_year + 1900);
        s.setstate(err);
      }
      return s;
    }
   --end example]

11A locale object may be extended with a new facet simply by  construct­
  ing  it  with  an instance of a class derived from locale::facet.  The
  only member a C++ program must define is the static member  id,  which
  identifies your class interface as a new facet.

12[Example: Classifying Japanese characters:
    // file: <jctype>
    #include <locale>
    namespace My {
      using namespace std;
      class JCtype : public locale::facet {
      public:
        static locale::id id;  // required for use as a new locale facet
        bool is_kanji(wchar_t c);
        JCtype() {}
      protected:
       ~JCtype() {}
      };
    }

    // file: filt.C
    #include <iostream>
    #include <locale>
    #include "jctype" // above
    std::locale::id JCtype::id;  // the static JCtype member declared above.
    int main()
    {
      using namespace std;
      typedef ctype<wchar_t> wctype;
      locale loc(locale(""),       // the user's preferred locale ...
                 new My::JCType);  // and a new feature ...
      wchar_t c = use_facet<wctype>(loc).widen('!');
      if (use_facet<My::JCType>(loc).is_kanji(c))
        cout << "no it isn't!" << endl;
      return 0;
    }

13The  new facet is used exactly like the built-in facets.   --end exam­
  ple]

14[Example: Replacing an existing facet is even easier.  Here we do  not
  define  a  member  id because we are reusing the numpunct<charT> facet
  interface:
    // my_bool.C
    #include <iostream>
    #include <locale>
    #include <string>
    namespace My {
      using namespace std;
      typedef numpunct_byname<char> cnumpunct;
      class BoolNames : public cnumpunct {
       protected:
        string do_truename()  { return "Oui Oui!"; }
        string do_falsename() { return "Mais Non!"; }
       ~BoolNames() {}
      public:
        BoolNames(const char* name) : cnumpunct(name) {}
      };
    }
    int main(int argc, char** argv)
    {
      using namespace std;
      // make the user's preferred locale, except for...
      locale loc(locale(""), new My::BoolNames(""));
      cout.imbue(loc);
      cout << boolalpha << "Any arguments today? " << (argc > 1) << endl;
      return 0;
    }
   --end example]

  22.3  C Library Locales                                [lib.c.locales]

1 Header <clocale> (Table 5):

                    Table 5--Header <clocale> synopsis

            +-------------------------------------------------+
            |   Type                    Name(s)               |
            +-------------------------------------------------+
            |Macros:                                          |
            |             LC_ALL        LC_COLLATE   LC_CTYPE |
            |             LC_MONETARY   LC_NUMERIC   LC_TIME  |
            |             NULL                                |
            +-------------------------------------------------+
            |Struct:      lconv                               |
            +-------------------------------------------------+
            |Functions:   localeconv    setlocale             |
            +-------------------------------------------------+

2 The contents are the same as the Standard C library.

  SEE ALSO: ISO C clause 7.4.