______________________________________________________________________

  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

     namespace std {
       // _lib.locale_, locale:
       class locale;
       template <class Facet> const Facet& use_facet(const locale&);
       template <class Facet> bool         has_facet(const locale&) throw();

       // _lib.locale.convenience_, convenience interfaces:
       template <class charT> bool isspace (charT c, const locale& loc);
       template <class charT> bool isprint (charT c, const locale& loc);
       template <class charT> bool iscntrl (charT c, const locale& loc);
       template <class charT> bool isupper (charT c, const locale& loc);
       template <class charT> bool islower (charT c, const locale& loc);
       template <class charT> bool isalpha (charT c, const locale& loc);
       template <class charT> bool isdigit (charT c, const locale& loc);
       template <class charT> bool ispunct (charT c, const locale& loc);
       template <class charT> bool isxdigit(charT c, const locale& loc);
       template <class charT> bool isalnum (charT c, const locale& loc);
       template <class charT> bool isgraph (charT c, const locale& loc);
       template <class charT> charT toupper(charT c, const locale& loc);
       template <class charT> charT tolower(charT c, const locale& loc);
       // _lib.category.ctype_ and _lib.facet.ctype.special_, ctype:
       class ctype_base;
       template <class charT> class ctype;
       template <>            class ctype<char>;             // specialization
       template <class charT> class ctype_byname;
       template <>            class ctype_byname<char>;      // specialization
       class codecvt_base;
       template <class internT, class externT, class stateT>
         class codecvt;
       template <class internT, class externT, class stateT>
         class codecvt_byname;
       // _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;
       // _lib.category.collate_, collation:
       template <class charT> class collate;
       template <class charT> class collate_byname;
       // _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;
       // _lib.category.monetary_, money:
       class money_base;
       template <class charT, class InputIterator>  class money_get;
       template <class charT, class OutputIterator> class money_put;
       template <class charT, bool Intl> class moneypunct;
       template <class charT, bool Intl> class moneypunct_byname;
       // _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)
  _________________________

  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);
         locale(const locale& other, const locale& one, category);
        ~locale() throw();           // non-virtual
         const locale& operator=(const locale& other) throw();
         template <class Facet> locale combine(const locale& other);
         // locale operations:
         basic_string<char>                  name() const;
         bool operator==(const locale& other) const;
         bool operator!=(const locale& other) const;
         template <class charT, class Traits, class Allocator>
           bool operator()(const basic_string<charT,Traits,Allocator>& s1,
                           const basic_string<charT,Traits,Allocator>& s2) const;
         // global locale objects:
         static       locale  global(const locale&);
         static const locale& classic();
       };
     }

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 function templates,
  use_facet<> and has_facet<>.

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

  _________________________
  1)  In  this  subclause, the type name struct tm is an incomplete type
  that is defined in <ctime>.
  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(s);
         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,A>&,
    basic_string<C,T,A>&)  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 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.

7 In successive calls to a locale facet member function during a call to
  an iostream inserter or extractor or a streambuf member function,  the
  returned  result  shall  be  identical.  [Note: This implies that such
  results may safely be reused without calling the locale  facet  member
  function  again,  and that member functions of iostream classes cannot
  safely call imbue() themselves, except as specified elsewhere.   --end
  note]

8 A  locale  constructed  from  a name string (such as "POSIX"), or from
  parts of two named locales, 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:

                     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<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_put<char>, money_put<wchar_t>              |
      +------------------------------------------------------------+
      |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_get<wchar_t>,               |
      |           time_put<char>, time_put<wchar_t>                |
      +------------------------------------------------------------+
      |messages   messages<char>, messages<wchar_t>                |
      +------------------------------------------------------------+

3 For  any  locale  loc either constructed, or returned by locale::clas-
  sic(), 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<C,InputIterator>,                         |
     |           money_put<C,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>             |
     +---------------------------------------------------------------+
     |messages   messages_byname<char>, messages_byname<wchar_t>     |
     +---------------------------------------------------------------+

5 The  provided  implementation  of members of facets num_get<charT> and
  num_put<charT>  calls  use_facet<F>(l)  only  for  facet  F  of  types
  numpunct<charT>  and ctype<charT>, and for locale l the value obtained
  by calling member getloc() on the ios_base& argument  to  these  func-
  tions.

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.require-
  ments_).   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.  A template formal parameter with  name  Interna-
  tional  represents  the  set  of all possible instantiations on a bool
  parameter.

  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  publicly-accessible
  declaration as follows:3)
           static ::std::locale::id id;
  Template parameters in this clause which are required to 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.

  --For      refs      ==     0,     the     implementation     performs
    delete static_cast<locale::facet*>(f) (where f is a pointer  to  the
    facet)   when  the  last  locale  object  containing  the  facet  is
    destroyed; for refs == 1,  the  implementation  never  destroys  the
    facet.

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]

  _________________________
  3)  This  is  a  complete list of requirements; there are no other re-
  quirements.  Thus, a facet class need not have a public copy construc-
  tor, assignment, default constructor, destructor, etc.

     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.
2 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();
3 Effects:
    Constructs a locale which is a copy of other.

     const locale& operator=(const locale& other) throw();
4 Effects:
    Creates a copy of other, replacing the current value.
5 Returns:
    *this

     explicit locale(const char* std_name);
6 Effects:
    Constructs a locale using standard C  locale  names,  e.g.  "POSIX".
    The  resulting  locale implements semantics defined to be associated
    with that name.
7 Throws:
    runtime_error if the argument is not valid, or is null.
8 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);
9 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).
10Throws:
    runtime_error if the argument is not valid, or is null.
11Notes:
    The locale has a name if and only if other has a name.

     template <class Facet> locale(const locale& other, Facet* f);
12Effects:
    Constructs a locale incorporating all facets from the first argument
    except that of type Facet, and installs the second argument  as  the
    remaining  facet.   If  f is null, the resulting object is a copy of
    other.
13Notes:
    The resulting locale has no name.

     locale(const locale& other, const locale& one, category cats);
14Effects:
    Constructs a locale incorporating all facets from the first argument
    except  those  that  implement  cats, which are instead incorporated
    from the second argument.
15Notes:
    The resulting locale has a name if and only if the first  two  argu-
    ments have names.

     ~locale() throw();

16A non-virtual destructor that throws no exceptions.

  22.1.1.3  locale members                          [lib.locale.members]

     template <class Facet> locale combine(const locale& other);
1 Effects:
    Constructs  a  locale incorporating all facets from *this except for
    that one facet of other that is identified by Facet.
2 Returns:
    The newly created locale.
3 Throws:
    runtime_error if has_facet<Facet>(other) is false.
4 Notes:
    The resulting locale has no name.

     basic_string<char>  name() const;
5 Returns:
    The name of *this, if it has one; otherwise,  the  string  "*".   If
    *this  has  a  name,  then  locale(name())  is  equivalent to *this.
    Details of the contents of the resulting string are otherwise imple-
    mentation-defined.

  22.1.1.4  locale operators                      [lib.locale.operators]

     bool operator==(const locale& other) const;
1 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;
2 Returns:
    The result of the expression: !(*this == other)

     template <class charT, class Traits, class Allocator>
       bool operator()(const basic_string<charT,Traits,Allocator>& s1,
                       const basic_string<charT,Traits,Allocator>& s2) const;
3 Effects:
    Compares two strings according to the collate<charT> facet.
4 Notes:
    This  member  operator template (and therefore locale itself) satis-
    fies requirements  for  a  comparator  predicate  template  argument
    (clause _lib.algorithms_) applied to strings.
5 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;

6 [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.
2 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.
3 Returns:
    The previous value of locale().

     static const locale& classic();

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

  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.
2 Returns:
    a reference to the corresponding facet of loc, if present.
3 Throws:
    bad_cast if has_facet<Facet>(loc) is false.
4 Notes:
    The reference returned remains valid at least as long as any copy of
    loc exists.

     template <class Facet> bool has_facet(const locale& loc) throw();
5 Returns:
    true if the facet requested is present in loc; otherwise false

  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);
     template <class charT> bool isprint (charT c, const locale& loc);
     template <class charT> bool iscntrl (charT c, const locale& loc);
     template <class charT> bool isupper (charT c, const locale& loc);
     template <class charT> bool islower (charT c, const locale& loc);
     template <class charT> bool isalpha (charT c, const locale& loc);
     template <class charT> bool isdigit (charT c, const locale& loc);
     template <class charT> bool ispunct (charT c, const locale& loc);
     template <class charT> bool isxdigit(charT c, const locale& loc);
     template <class charT> bool isalnum (charT c, const locale& loc);
     template <class charT> bool isgraph (charT c, const locale& loc);

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;
1 Returns:
    use_facet<ctype<charT> >(loc).toupper(c).

     template <class charT> charT tolower(charT c, const locale& loc) const;
2 Returns:
    use_facet<ctype<charT> >(loc).tolower(c).

  _________________________
  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.

  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.

2 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 c) 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;
       };

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

2 The instantiations required in Table 2 (_lib.locale.category_), namely
  ctype<char> and ctype<wchar_t>, implement 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;
1 Returns:
    do_is(m,c) or do_is(low,high,vec)

     const charT* scan_is(mask m,
                          const charT* low, const charT* high) const;
2 Returns:
    do_scan_is(m,low,high)

     const charT* scan_not(mask m,
                           const charT* low, const charT* high) const;
3 Returns:
    do_scan_not(m,low,high)

     charT        toupper(charT) const;
     const charT* toupper(charT* low, const charT* high) const;
4 Returns:
    do_toupper(c) or do_toupper(low,high)

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

5 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;
6 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;
7 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;
1 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 identifies a value M of type ctype_base::mask for  each  *p
    where (low<=p && p<high), and places it into vec[p-low].
2 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;
3 Effects:
    Locates a character in a buffer that conforms to a classification m.
4 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;
5 Effects:
    Locates a character in a buffer that fails to conform to a classifi-
    cation m.
6 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;
7 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.
8 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;
9 Effects:
    Converts  a  character or characters to lower 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.
10Returns:
    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;
11Effects:
    Applies  the simplest reasonable transformation from a char value or
    sequence  of  char  values  to  the  corresponding  charT  value  or
    values.5) The only characters for which unique  transformations  are
    required   are   those   in   the   basic   source   character   set
    (_lex.charset_).
    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.6)
    The  second  form  transforms  each  character *p in the range [low,
    high), placing the result in dest[p-low].
12Returns:
    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;
13Effects:
    Applies the simplest reasonable transformation from a charT value or
    sequence of charT values to the corresponding char value or  values.
    For any character c in the basic source character set(_lex.charset_)
    the transformation is such that
       do_widen(do_narrow(c),0) == c
    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
  _________________________
  5)  The char argument of do_widen is intended to accept values derived
  from character literals for conversion the locale's encoding.
  6) In other words, the transformed character is not a  member  of  any
  character classification that c is not also a member of.

    (or  dfault  if  no  simple  transformation  is readly available) in
    dest[p-low].
14Returns:
    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]
     namespace std {
       template <class charT>
       class ctype_byname : public ctype<charT> {
       public:
         typedef ctype<charT>::mask mask;
         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 {
       template <> 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;
         static const size_t table_size = IMPLEMENTATION_DEFINED;
       protected:
         const mask* table() const throw();
         static const mask* classic_table() throw();
        ~ctype();                    // virtual
         virtual char        do_toupper(char c) const;
         virtual const char* do_toupper(char* low, const char* high) const;
         virtual char        do_tolower(char c) const;
         virtual const char* do_tolower(char* low, const char* high) const;

         virtual char        do_widen(char c) const;
         virtual const char* do_widen(const char* low,
                                      const char* high,
                                      char* to) const;
         virtual char        do_narrow(char c, char dfault) const;
         virtual const char* do_narrow(const char* low,
                                       const char* high,
                                       char dfault, char* to) const;
       };
     }

1 A  specialization ctype<char> is provided so that the member functions
  on  type  char can be implemented inline.7) The implementation-defined
  value of member table_size is at least 256.

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

     ~ctype();
1 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]

1 In the following member descriptions, for unsigned char values v where
  (v >= table_size), table()[v] is assumed to  have  an  implementation-
  defined  value (possibly different for each such value v) without per-
  forming the array lookup.

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

  _________________________
  7) 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>.

2 Precondition:
    tbl either 0 or an array of at least table_size elements.
3 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;
4 Effects:
    The second form, for all *p in the range [low, high), assigns vec[p-
    low] to table()[(unsigned char)*p].
5 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;
6 Returns:
    The smallest p in the range [low, high) such that
       table()[(unsigned char) *p] & m
    is true.

     const char* scan_not(mask m,
                          const char* low, const char* high) const;
7 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;
8 Returns:
    do_toupper(c) or do_toupper(low,high)

     char        tolower(char c) const;
     const char* tolower(char* low, const char* high) const;
9 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;
10Returns:
    do_widen(low, high, to).

     char        narrow(char c, char /*dfault*/) const;
     const char* narrow(const char* low, const char* high,
                        char /*dfault*/, char* to) const;
11Returns:
    do_narrow(low, high, to).

     const mask* table() const throw();
12Returns:
    The first  constructor  argument,  if  it  was  non-zero,  otherwise

    classic_table().

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

     static const mask* classic_table() throw();
1 Returns:
    A pointer to the initial element of  an  array  of  size  table_size
    which  represents  the  classifications  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;

     virtual char        do_widen(char c) const;
     virtual const char* do_widen(const char* low,
                                  const char* high,
                                  char* to) const;
     virtual char        do_narrow(char c, char dfault) const;
     virtual const char* do_narrow(const char* low,
                                   const char* high,
                                   char dfault, char* to) 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>
     namespace std {
       template <> class ctype_byname<char> : public ctype<char> {
       public:
         explicit ctype_byname(const char*, size_t refs = 0);
       protected:
        ~ctype_byname();             // virtual
         virtual char        do_toupper(char c) const;
         virtual const char* do_toupper(char* low, const char* high) const;
         virtual char        do_tolower(char c) const;
         virtual const char* do_tolower(char* low, const char* high) const;

         virtual char        do_widen(char c) const;
         virtual const char* do_widen(char* low,
                                      const char* high,
                                      char* to) const;
         virtual char        do_widen(char c) const;
         virtual const char* do_widen(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 internT, class externT, class stateT>
      class codecvt : public locale::facet, public codecvt_base {
      public:
       typedef internT  intern_type;
       typedef externT  extern_type;
       typedef stateT state_type;
       explicit codecvt(size_t refs = 0)
       result out(stateT& state,
        const internT* from, const internT* from_end, const internT*& from_next,
              externT*   to,       externT* to_limit, externT*& to_next) const;
       result unshift(stateT& state,
              externT*   to,        externT* to_limit, externT*& to_next) const;
       result in(stateT& state,
        const externT* from, const externT* from_end, const externT*& from_next,
              internT*   to,       internT* to_limit, internT*& to_next) const;
       int encoding() const throw();
       bool always_noconv() const throw();
       int length(const stateT&, const externT* from, const externT* end,
                  size_t max) const;
       int max_length() const throw();
       static locale::id id;
      protected:
       ~codecvt();                   // virtual
       virtual result do_out(stateT& state,
        const internT* from, const internT* from_end, const internT*& from_next,
              externT* to,         externT* to_limit, externT*& to_next) const;
       virtual result do_in(stateT& state,
        const externT* from, const externT* from_end, const externT*& from_next,
              internT* to,         internT* to_limit, internT*& to_next) const;
       virtual result do_unshift(stateT& state,
              externT* to,         externT* to_limit, externT*& to_next) const;
       virtual int do_encoding() const throw();
       virtual bool do_always_noconv() const throw();
       virtual int do_length(const stateT&, const externT* from,
                             const externT* end, size_t max) const;
       virtual int do_max_length() const throw();
      };
     }

1 The  class  codecvt<internT,externT,stateT> is for use when converting
  from one codeset to another, such as from wide characters to multibyte
  characters,  between wide character encodings such as Unicode and EUC.

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

3 The  instantiations  required  in the Table 2 (_lib.locale.category_),
  namely               codecvt<wchar_t,char,mbstate_t>               and

  codecvt<char,char,mbstate_t>,   convert   the   implementation-defined
  native   character  set.   codecvt<char,char,mbstate_t>  implements  a
  degenerate   conversion;    it    does    not    convert    at    all.
  codecvt<wchar_t,char,mbstate_t>  converts between the native character
  sets for tiny and wide characters.  Instantiations on  mbstate_t  per-
  form  conversion  between  encodings known to the library implementor.
  Other encodings can be converted by  specializing  on  a  user-defined
  stateT  type.   The stateT object can contain any state that is useful
  to communicate to or from the specialized do_convert member.

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

     result out(stateT& state,
       const internT* from, const internT* from_end, const internT*& from_next,
             externT* to, externT* to_limit, externT*& to_next) const;
1 Returns:
    do_out(state, from, from_end, from_next, to,to_limit, to_next)

     result unshift(stateT& state,
             externT* to, externT* to_limit, externT*& to_next) const;
2 Returns:
    do_unshift(state, to, to_limit, to_next)

     result in(stateT& state,
       const externT* from, const externT* from_end, const externT*& from_next,
             internT* to, internT* to_limit, internT*& to_next) const;
3 Returns:
    do_in(state, from,from_end,from_next, to,to_limit,to_next)

     int encoding() const throw();
4 Returns:
    do_encoding()

     bool always_noconv() const throw();
5 Returns:
    do_always_noconv()

     int length(stateT& state, const externT* from, const externT* from_end,
                size_t max) const;
6 Returns:
    do_length(state, from,from_end,max)

     int max_length() const throw();
7 Returns:
    do_max_length()

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

     result do_out(stateT& state,
       const internT* from, const internT* from_end, const internT*& from_next,
       externT* to, externT* to_limit, externT*& to_next) const;

     result do_in(stateT& state,
       const externT* from, const externT* from_end, const externT*& from_next,
             internT* to, internT* to_limit, internT*& to_next) const;
1 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.
2 Effects:
    Translates  characters  in the source range [from,from_end), placing
    the results in sequential  positions  starting  at  destination  to.
    Converts no more than (from_end-from) source elements, and stores no
    more than (to_limit-to) destination 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 element 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]
3 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]
4 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 available
    destination elements, or that additional source elements are  needed
    before another destination element can be produced.

     result do_unshift(stateT& state,
       externT* to, externT* to_limit, externT*& to_next) const;
5 Effects
    Places  characters  starting at to that should be appended to termi-
    nate a sequence when the current stateT is  given  by  state.8)  The
  _________________________
  8) Typically these will be characters to return the state to stateT()

    instantiations  required  in Table 2 (_lib.locale.category_), namely
    codecvt<wchar_t,char,mbstate_t>  and   codecvt<char,char,mbstate_t>,
    store  no characters.  Stores no more than (to_limit-to) destination
    elements.  It always leaves the to_next pointer pointing one  beyond
    the last element successfully stored.
6 Returns
    An enumeration value, as summarized in Table 5:

                       Table 5--convert result values

   +----------------------------------------------------------------------+
   | Value                              Meaning                           |
   +----------------------------------------------------------------------+
   |ok        completed the sequence                                      |
   |partial   more characters need to be supplied to complete termination |
   |error     state has invalid value.                                    |
   |noconv    no termination is needed for this state_type                |
   +----------------------------------------------------------------------+
    codecvt<char,char,mbstate_t>, returns noconv.

     int do_encoding() const throw();
7 Returns:
    -1  if the encoding of the externT sequence is state-dependent; else
    the constant number of  externT  characters  needed  to  produce  an
    internal character; or 0 if this number is not a constant9).

     bool do_always_noconv() const throw();
8 Returns:
    true if do_convert() returns noconv for all valid  argument  values.
    codecvt<char,char,mbstate_t> returns true.

     int do_length(stateT& state, const externT* from, const externT* from_end,
                   size_t max) const;
9 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.
10Returns:
    (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  internT.   The  instantiations   required   in   Table   2
    (_lib.locale.category_),  namely  codecvt<wchar_t,  char, mbstate_t>
    and codecvt<char, char, mbstate_t>, return the  lesser  of  max  and
    (from_end-from).
  _________________________
  9)  If  encoding() yields -1, then more than max_length() externT ele-
  ments may be consumed when producing a single internT  character,  and
  additional  externT elements may appear at the end of a sequence after
  those that yield the final internT character.

     int do_max_length() const throw();
11Returns:
    The  maximum  value  that do_length(state,from,nfrom_end, can return
    for  any  valid  range  [from,from_end)  and  stateT  value   state.
    codecvt<char, char, mbstate_t> returns 1.

  22.2.1.6  Template class                   [lib.locale.codecvt.byname]
       codecvt_byname
     namespace std {
      template <class internT, class externT, class stateT>
      class codecvt_byname : public codecvt<internT, externT, stateT> {
      public:
       explicit codecvt_byname(const char*, size_t refs = 0);
      protected:
      ~codecvt_byname();             // virtual
       virtual result do_out(stateT& state,
         const internT* from, const internT* from_end, const internT*& from_next,
               externT* to,         externT* to_limit, externT*& to_next) const;
       virtual result do_in(stateT& state,
         const externT* from, const externT* from_end, const externT*& from_next,
               internT* to,         internT* to_limit, internT*& to_next) const;
       virtual result do_unshift(stateT& state,
               externT* to,         externT* to_limit, externT*& to_next) const;
       virtual int do_encoding() const throw();
       virtual bool do_always_noconv() const throw();
       virtual int do_length(const stateT&, const externT* from,
                             const externT* end, size_t max) const;
       virtual result do_unshift(stateT& state,
              externT* to, externT* to_limit, externT*& to_next) 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.10)

2 All  specifications of member functions for num_put and num_get in the
  subclauses of _lib.category.numeric_ only apply to the  instantiations
  required   in   Tables   2   and   3  (_lib.locale.category_),  namely
  num_get<char>,       num_get<wchar_t>,       num_get<C,InputIterator>,
  num_put<char>, num_put<wchar_t>, and num_put<C,OutputIterator>.  These
  instantiations refer to the ios_base& argument for formatting specifi-
  cations  (_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 classification.
  _________________________
  10) Parsing "-1" correctly into (e.g.) an unsigned short requires that
  the corresponding member get() at least extract the sign before  dele-
  gating.

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);
         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;
         iter_type get(iter_type in, iter_type end, ios_base&,
                       ios_base::iostate& err, void*& 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;
         virtual iter_type do_get(iter_type, iter_type, ios_base&,
             ios_base::iostate& err, void*& 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, 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;
     iter_type get(iter_type in, iter_type end, ios_base& str,
                   ios_base::iostate& err, void*& val) const;
1 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, 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;
     iter_type do_get(iter_type in, iter_type end, ios_base& str,
                      ios_base::iostate& err, void*& val) const;
1 Effects:
    Reads  characters  from   in,   interpreting   them   according   to
    str.flags(),   use_facet<   ctype<charT>   >(loc),   and  use_facet<
    numpunct<charT> >(loc), where loc  is  str.getloc().   If  an  error
    occurs,  val  is  unchanged;  otherwise  it  is set to the resulting
    value.

2 The details of this operation occur in three stages

  --Stage 1: Determine a conversion specifier

  --Stage 2: Extract characters from in and  determine  a  corresponding
    char  value  for the format expected by the conversion specification
    determined in stage 1.

  --Stage 3: Store results
    The details of the stages are presented below.  in.
3 Stage 1:
    The function initializes local variables via
           fmtflags flags = str.flags();
           fmtflags basefield = (flags & ios_base::basefield);
           fmtflags uppercase = (flags & ios_base::uppercase);
           fmtflags boolalpha = (flags & ios_base::boolalpha);
4   For conversion to an integral  type,  the  function  determines  the
    integral conversion specifier as indicated in Table 6.  The table is
    ordered.  That is, the first line whose condition is true applies.

                        Table 6--Integer conversions

                +------------------------------------------+
                |        State            stdio equivalent |
                +------------------------------------------+
                |basefield == oct                %o        |
                +------------------------------------------+
                |basefield == hex                %X        |
                +------------------------------------------+
                |basefield == 0                  %i        |
                +------------------------------------------+
                |signed integral type            %d        |
                +------------------------------------------+
                |unsigned integral type          %u        |
                +------------------------------------------+
5   For conversions to a  floating type the specifier is %g.
6   For conversions to void* the specifier is %p.
7   A length specifier is added  to  the  conversion  specification,  if
    needed, as indicated in Table  7.

                          Table 7--Length Modifier

                     +---------------------------------+
                     |     type        length modifier |
                     +---------------------------------+
                     |short                   h        |
                     +---------------------------------+
                     |unsigned short          h        |
                     +---------------------------------+
                     |long                    l        |
                     +---------------------------------+
                     |unsigned long           l        |
                     +---------------------------------+
                     |long double             L        |
                     +---------------------------------+
8 Stage 2:
    If in==end then stage 2 terminates.  Otherwise a charT is taken from
    in and local variables are initialized as if by
           char_type ct = *in ;
           char c = src[find(atoms, atoms + sizeof(src) - 1, ct) - atoms];
           if ( ct ==  use_facet<numpunct<charT> >(loc).decimal_point() )
               c = '.';
           bool discard =
               ( ct == use_facet<numpunct<charT> >(loc).thousands_sep()
                   &&
                use_facet<numpunct<charT> >(loc).grouping().length() != 0 );
    where the values src and atoms are defined as if by:
           static const char src[] = "0123456789abcdefABCDEF+-";
           char_type atoms[sizeof(src)];
           use_facet<ctype<charT> >(loc).widen(src, src + sizeof(src), atoms);
    for this value of loc.
9   If discard is true then the position of the character is remembered,
    but  the  character  is  otherwise ignored.  If it is not discarded,
    then a check is made to determine if c is allowed as the next  char-
    acter  of  an  input  field  of the conversion specifier returned by
    stage 1.  If so it is accumulated.
10  If the character is either  discarded  or  accumulated  then  in  is
    advanced by ++in and processing returns to the beginning of stage 2.
11Stage 3:
    The result of stage 2 processing can be one of

  --A sequence of chars has been accumulated in stage  2  that  is  con-
    verted  (according  to the rules of scanf) to a value of the type of
    val.  This value is stored in val and ios_base::goodbit is stored in
    err.

  --The sequence of chars accumulated in stage 2 would have caused scanf
    to report an input failure.  ios_base::failbit is assigned to err.

12Digit grouping is checked.  That is, the positions of discarded  sepa-
  rators  is  examined  for  consistency  with use_facet<numpunct<charT>
  >(loc).grouping().  If they are not consistent then  ios_base::failbit
  is assigned to err.

13In  any  case,  if  stage  2 processing was terminated by the test for
  in==end then err|=ios_base::eofbit is performed.

     iter_type do_get(iter_type in, iter_type end, ios_base& str,
                      ios_base::iostate& err, bool& val) const;
14Effects:
    If (str.flags()&&ios_base::boolalpha)==0 then input proceeds  as  it
    would  for  a  long except that if a value is being stored into val,
    the value is determined according to the following: If the value  to
    be stored is 0 then false is stored.  If the value is 1 then true is
    stored.  Otherwise err|=ios_base::failbit is performed and no  value
    is stored.

15Otherwise  a  target  string  to  be  matched is determined by calling
  either       use_facet<ctype<charT>        >(loc).truename()        or
  use_facet<ctype<charT>  >(loc).falsename() depending on whether val is
  true or false (respectively).

16As long as in!=end and characters continue to match the target  string
  charT's  are  obtained  by doing *in++.  A value is assigned to err as
  follows

  --If the target string was matched completely, then goodbit.

  --If input was terminated because in==end, then eofbit

  --Otherwise, failbit.
17Returns:
    in.

  22.2.2.2  Template class num_put                   [lib.locale.nm.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;
         iter_type put(iter_type s, ios_base& f, char_type fill,
                       const void* 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;
         virtual iter_type do_put(iter_type, ios_base&, char_type fill,
                                  const void* 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;
     iter_type put(iter_type out, ios_base& str, char_type fill,
                   const void* val) const;
1 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;
     iter_type do_put(iter_type out, ios_base& str, char_type fill,
                      const void* val) const;
1 Effects:
    Writes characters to the sequence out, formatting  val  as  desired.

    In the following description, a local variable initialized with
           locale loc = str.getloc();

2 The details of this operation occur in several stages:

  --Stage  1: Determine a printf conversion specifier spec and determin-
    ing the characters that would be  printed  by  printf(_lib.c.files_)
    given this conversion specifier for
           printf(spec, val)
    assuming that the current locale is the "C" locale.

  --Stage  2:  Adjust  the representation by converting each char deter-
    mined by stage 1 to a charT using a conversion and  values  returned
    by members of use_facet< numpunct<charT> >(str.getloc())

  --Stage 3: Determine where padding is required.

  --Stage 4: Insert the sequence into the out.
3   Detailed descriptions of each stage follow.
4 Returns:
    out.

5 Stage 1:
    The  first action of stage 1 is to determine a conversion specifier.
    The tables that describe this determination use the following  local
    variables
           fmtflags flags = str.flags() ;
           fmtflags basefield =  (flags & (ios_base::basefield));
           fmtflags uppercase =  (flags & (ios_base::uppercase));
           fmtflags floatfield = (flags & (ios_base::floatfield));
           fmtflags showpos =    (flags & (ios_base::showpos));
           fmtflags showbase =   (flags & (ios_base::showbase));
6    All  tables  used  in describing stage 1 are ordered.  That is, the
    first line whose condition is true applies.  A line without a condi-
    tion is the default behavior when none of the earlier lines apply.
7    For  conversion  from an integral type other than a character type,
    the function determines the integral conversion specifier  as  indi-
    cated in Table 8.

                        Table 8--Integer conversions

      +---------------------------------------------------------------+
      |                   State                      stdio equivalent |
      +---------------------------------------------------------------+
      |basefield == ios_base::oct                           %o        |
      +---------------------------------------------------------------+
      |(basefield == ios_base::hex) && !uppercase           %x        |
      +---------------------------------------------------------------+
      |(basefield == ios_base::hex)                         %X        |
      +---------------------------------------------------------------+
      |for a signed integral type                           %d        |
      +---------------------------------------------------------------+
      |for an unsigned integral type                        %u        |
      +---------------------------------------------------------------+
8    For  conversion from a floating-point type, the function determines
    the floating-point conversion specifier as indicated in Table 9:

                    Table 9--Floating-point conversions

    +--------------------------------------------------------------------+
    |                     State                         stdio equivalent |
    +--------------------------------------------------------------------+
    |floatfield == ios_base::fixed                             %f        |
    +--------------------------------------------------------------------+
    |floatfield == ios_base::scientific && !uppercase          %e        |
    +--------------------------------------------------------------------+
    |floatfield == ios_base::scientific                        %E        |
    +--------------------------------------------------------------------+
    |!uppercase                                                %g        |
    +--------------------------------------------------------------------+
    |otherwise                                                 %G        |
    +--------------------------------------------------------------------+
9   For conversions from an integral or floating type a length  modifier
    is added to the conversion specifier as indicated in  Table 10.

                         Table 10--Length modifier

                     +--------------------------------+
                     |    type        length modifier |
                     +--------------------------------+
                     |long                   l        |
                     +--------------------------------+
                     |unsigned long          l        |
                     +--------------------------------+
                     |long double            L        |
                     +--------------------------------+
                     |otherwise            none       |
                     +--------------------------------+
10  The conversion specifier has the following optional additional qual-
    ifiers prepended as indicated in Table 11:

                       Table 11--Numeric conversions

      +--------------------------------------------------------------+
      |       Type(s)                State          stdio equivalent |
      +--------------------------------------------------------------+
      |an integral type        flags & showpos             +         |
      |                        flags & showbase            #         |
      +--------------------------------------------------------------+
      |a floating-point type   flags & showpos             +         |
      |                        flags & showpoint           #         |
      +--------------------------------------------------------------+
11  For conversion from a floating-point type, if (flags & fixed)  !=  0
    or  if str.precision() > 0, then str.precision() is specified in the
    conversion specification.
12  For conversion from void* the specifier is %p.
13  The representations at the end of stage 1  consists  of  the  char's
    that  would  be  printed  by a call of printf(s, val) where s is the
    conversion specifier determined above.

14Stage 2:
    Any character c other than a decimal  point(.)  is  converted  to  a
    charT via use_facet<ctype<charT> >(loc).widen(c)

15A local variable punct is initialized via
         numpunct<charT> punct = use_facet< numpunct<charT> >(str.getloc())
16   For  integral  types, punct.thousands_sep() characters are inserted
    into  the  sequence  as  determined  by  the   value   returned   by
    punct.do_grouping()     using     the     method     described    in
    _lib.facet.numpunct.virtuals_
17  Decimal point characters(.) are replaced by punct.decimal_point()

18Stage 3:
    A local variable is initialized as
           fmtflags adjustfield=   (flags & (ios_base::adjustfield));
19  The location of any padding11) is determined according to Table 12:

                           Table 12--Fill padding

           +----------------------------------------------------+
           |            State                     Location      |
           +----------------------------------------------------+
           |adjustfield == ios_base::left    pad after          |
           +----------------------------------------------------+
           |adjustfield == ios_base::right   pad before         |
           +----------------------------------------------------+
           |adjustfield == internal and a    pad after the sign |
           |sign occurs in the representa-                      |
           |tion                                                |
           +----------------------------------------------------+
           |adjustfield == internal and      pad after x or X   |
           |representation after stage 1                        |
           |began with 0x 1or 0X                                |
           +----------------------------------------------------+
           |otherwise                        pad before         |
           +----------------------------------------------------+
20   If str.width() is nonzero and the number of charT's in the sequence
    after stage 2 is less than str.width(), then enough fill  characters
    are  added  to the sequence at the position indicated for padding to
    bring the length of the sequence to str.width().
21  str.width(0) is called.

22Stage 4:
    The sequence of charT's at the end of stage 3 are output via
           *out++ = c

     iter_type put(iter_type out, ios_base& str, char_type fill,
                   bool val) const;
23Effects:
    If (str.flags()&ios_base::boolalpha)==0 then do
           out = do_put(out, str, fill, (int)val)
    Otherwise do
           string_type s =
               val ? use_facet<ctype<charT> >(loc).truename()
                         : use_facet<ctype<charT> >(loc).falsename() ;
    and then insert the characters of s into out.  out.

  _________________________
  11) The conversion specification #o generates a leading 0 which is not
  a padding character.

  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 instantiations required
  in  Table  2  (_lib.locale.category_),  namely  numpunct<wchar_t>  and
  numpunct<char>, provide classic C" numeric formats, i.e. they  contain
  information  equivalent  to  that  contained in the C" locale or their
  wide character counterparts as if obtained by a call to widen.

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.

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

     char_type decimal_point() const;

1 Returns:
    do_decimal_point()

     char_type thousands_sep() const;
2 Returns:
    do_thousands_sep()

     string grouping()  const;
3 Returns:
    do_grouping()

     string_type truename()  const;
     string_type falsename() const;
4 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;
1 Returns:
    A  character  for  use as the decimal radix separator.  The required
    instantiations return '.' or L'.'.

     string_type do_thousands_sep() const;
2 Returns:
    A character for use as the  digit  group  separator.   The  required
    instantiations return ',' or L','.

     string do_grouping() const;
3 Returns:
    A  basic_string<char>  vec  used  as  a vector of integer values, in
    which each element vec[i] represents the number of digits12) 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 required instantiations return the empty string,  indicating  no
    grouping.

     string_type do_truename()  const;
     string_type do_falsename() const;
4 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",
    or L"true" and L"false".

  _________________________
  12) Thus, the string "\003" specifies groups of 3 digits each, and "3"
  probably  indicates  groups  of  51 (!) digits each, because 51 is the
  ASCII value of "3".

  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:
         typedef charT                char_type;
         typedef basic_string<charT>  string_type;
         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  (clause
  _lib.algorithms_) and containers operating on strings.  The instantia-
  tions  required  in  Table  2  (_lib.locale.category_),  namely   col-
  late<char>   and   collate<wchar_t>,   apply   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;
1 Returns:
    do_compare(low1, high1, low2, high2)

     string_type transform(const charT* low, const charT* high) const;
2 Returns:
    do_transform(low, high)

     long hash(const charT* low, const charT* high) const;
3 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;
1 Returns:
    1 if the first string is greater than the second, -1 if  less,  zero
    otherwise.    The   instantiations   required   in   the   Table   2
    (_lib.locale.category_), namely collate<char> and  collate<wchar_t>,
    implement a lexicographical comparison (_lib.alg.lex.comparison_).

     string_type do_transform(const charT* low, const charT* high) const;
2 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.13)

     long do_hash(const charT* low, const charT* high) const;
3 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,
    approaching  (1.0/numeric_limits<unsigned  long>::max()).      --end
    note]

  22.2.4.2  Template class                   [lib.locale.collate.byname]
       collate_byname

  _________________________
  13)  This function is useful when one string is being compared to many
  other strings.

     namespace std {
       template <class charT>
       class collate_byname : public collate<charT> {
       public:
         typedef basic_string<charT> string_type;
         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 Templates time_get<charT,InputIterator> and time_put<charT,OutputIter-
  ator> provide date and time formatting and  parsing.   All  specifica-
  tions  of member functions for time_put and time_get in the subclauses
  of _lib.category.time_ only apply to the  instantiations  required  in
  Tables  2  and  3  (_lib.locale.category_).   Their  members use their
  ios_base&, ios_base::iostate&, and  fill  arguments  as  described  in
  (_lib.locale.categories_), and the ctype<> facet, to determine format-
  ting 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) 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.14)

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

     dateorder date_order() const;
1 Returns:
    do_date_order()

     iter_type get_time(iter_type s, iter_type end, ios_base& str,
                        ios_base::iostate& err, tm* t) const;
2 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;
3 Returns:
    do_get_date(s, end, str, err, t)

     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;
4 Returns:
    do_get_weekday(s, end, str, err, t) or do_get_monthname(s, end, str,
    err, t)

  _________________________
  14) 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_year(iter_type s, iter_type end, ios_base& str,
                        ios_base::iostate& err, tm* t) const;
5 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;
1 Returns:
    An enumeration value indicating the preferred  order  of  components
    for those date formats that are composed of day, month, and year.15)
    Returns  no_order if the date format specified by 'x' contains other
    variable components (e.g. Julian day, week number, week day).

     iter_type do_get_time(iter_type s, iter_type end, ios_base& str,
                           ios_base::iostate& err, tm* t) const;
2 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.
3 Returns:
    An  iterator  pointing  immediately beyond the last character recog-
    nized as possibly part of a valid time.

     iter_type do_get_date(iter_type s, iter_type end, ios_base& str,
                           ios_base::iostate& err, tm* t) const;
4 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.
5 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;
6 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.
7 Returns:
    An iterator pointing immediately beyond the  last  character  recog-
    nized as part of a valid name.
  _________________________
  15)  This  function is intended as a convenience only, for common for-
  mats, and may return no_order in valid locales.

     iter_type do_get_year(iter_type s, iter_type end, ios_base& str,
                           ios_base::iostate& err, tm* t) const;
8 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.
9 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:
         typedef time_base::dateorder dateorder;
         typedef InputIterator        iter_type

         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& str, char_type fill, const tm* t,
                   const charT* pattern, const charT* pat_end) const;
     iter_type put(iter_type s, ios_base& str, char_type fill, const tm* t,
                   char format, char modifier = 0) const;
1 Effects:
    The first form steps through the sequence from pattern to end, iden-
    tifying characters that are part of a format sequence.  Each charac-
    ter  that  is  not part of a format sequence is written to s immedi-
    ately, and each format sequence, as it is identified, results  in  a
    call  to  do_put;  thus,  format  elements  and other characters are
    interleaved in the output in the order in which they appear  in  the
    pattern.  Format sequences are identified by converting each charac-
    ter c to a char value as if by ct.narrow(c, 0), where ct is a refer-
    ence  to ctype<charT> obtained from str.getloc().  The first charac-
    ter of each sequence is equal to '%', followed by an optional  modi-
    fier character mod16) and  a  format  specifier  character  spec  as
    defined for the function strftime.  If no modifier character is pre-
    sent, mod is zero.  For each valid format sequence identified, calls
    do_put(s, str, fill, t, spec, mod).

2 The second form calls do_put(s, str, fill, t, format, modifier).
3 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;
1 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().17) except that the sequence of characters  produced  for
    those specifiers that are described as depending on the C locale are
    instead implementation-defined.18)
  _________________________
  16)  Although  the  C  programming language defines no modifiers, most
  vendors do.
  17) Interpretation of the modifier argument is implementation-defined,
  but should follow POSIX conventions.
  18) Implementations are encouraged to refer to other  standards  (such
  as POSIX) for these definitions.

2 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:
         typedef charT          char_type;
         typedef OutputIterator iter_type;

         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 All  specifications of member functions for money_put and money_get in
  the subclauses of _lib.category.monetary_ only apply to the instantia-
  tions  required in Tables 2 and 3 (_lib.locale.category_).  Their mem-
  bers 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.

  22.2.6.1  Template class money_get              [lib.locale.money.get]
     namespace std {
       template <class charT,
                 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, bool intl,
                       ios_base& f, ios_base::iostate& err,
                       long double& units) const;
         iter_type get(iter_type s, iter_type end, bool intl,
                       ios_base& f, ios_base::iostate& err,
                       string_type& digits) const;
         static locale::id id;

       protected:
        ~money_get();                // virtual
         virtual iter_type do_get(iter_type, iter_type, bool, ios_base&,
                          ios_base::iostate& err, long double& units) const;
         virtual iter_type do_get(iter_type, iter_type, bool, 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, bool intl,
                   ios_base& f, ios_base::iostate& err,
                   long double& quant) const;
     iter_type get(s, iter_type end, bool intl, ios_base&f,
                   ios_base::iostate& err, string_type& quant) const;
1 Returns:
    do_get(s, end, intl, 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, bool intl,
                      ios_base& str, ios_base::iostate& err,
                      long double& units) const;
     iter_type do_get(iter_type s, iter_type end, bool intl,
                      ios_base& str, ios_base::iostate& err,
                      string_type& digits) const;
1 Effects:
    Reads characters from s to parse  and  construct  a  monetary  value
    according to the format specified by a moneypunct<charT, Intl> facet
    reference mp and the character mapping specified by  a  ctype<charT>
    facet  reference  ct  obtained  from the locale returned by str.get-
    loc(), and str.flags().  If a valid sequence is recognized, does not
    change   err;   otherwise,   sets   err   to  (err|str.failbit),  or
    (err|str.failbit|str.eofbit) if no more  characters  are  available,
    and  does  not change units or digits.  Uses the pattern returned by
    mp.neg_format() to parse all values.  The result is returned  as  an
    integral  value  stored in units or as a sequence of digits possibly
    preceded by a minus sign (as produced by ct.widen(c) where c is  '-'
    or  in  the range from '0' through '9', inclusive) stored in digits.
    [Example: The sequence $1,056.23 in a common  United  States  locale
    would  yield,  for  units, 105623, or, for digits, "105623".   --end
    example] If mp.grouping() indicates that no thousands separators are
    permitted,  any  such characters are not read, and parsing is termi-
    nated at the point where they first  appear.   Otherwise,  thousands
    separators  are  optional;  if present, they are checked for correct
    placement only after all format components have been read.

2 Where space or none appears in the format pattern, except at the  end,
  optional  white  space  (as recognized by ct.is) is consumed after any
  required space.  If (str.flags() & str.showbase) is  false,  the  cur-
  rency  symbol is optional and is consumed only if other characters are
  needed to complete the  format;  otherwise,  the  currency  symbol  is

  required.

3 If the first character (if any) in the string pos returned by mp.posi-
  tive_sign() or the string neg returned by mp.negative_sign() is recog-
  nized  in  the position indicated by sign in the format pattern, it is
  consumed and any remaining characters in the string are required after
  all  the  other format components.  [Example: If showbase is off, then
  for a neg value of "()" and a currency symbol of "L", in "(100 L)" the
  "L"  is  consumed;  but if neg is "-", the "L" in "-100 L" is not con-
  sumed.  ] If pos or neg is empty, the sign component is optional,  and
  if  no sign is detected, the result is given the sign that corresponds
  to the source of the empty string.  Otherwise, the  character  in  the
  indicated  position  must match the first character of pos or net, and
  the result is given the corresponding sign.  If the first character of
  pos  is  equal  to  the first character of neg, or if both strings are
  empty, the result is given a positive sign.

4 Digits in the numeric monetary component are extracted and  placed  in
  digits,  or  into  a character buffer buf1 for conversion to produce a
  value for units, in the order in which  they  appear,  preceded  by  a
  minus  sign if and only if the result is negative.  The value units is
  produced as if by19)
     for (int i = 0; i < n; ++i)
             buf2[i] = src[find(atoms, atoms+sizeof(src), buf1[i]) - atoms];
     buf2[n] = 0;
     sscanf(buf2, "%Lf", &units);
  where n is the number of characters placed in buf1, buf2 is a  charac-
  ter buffer, and the values src and atoms are defined as if by
     static const char src[] = "0123456789-";
     charT atoms[sizeof(src)];
     ct.widen(src, src + sizeof(src) - 1, atoms);
5 Returns:
    An  iterator  pointing  immediately beyond the last character recog-
    nized as part of a valid monetary quantity.

  22.2.6.2  Template class money_put              [lib.locale.money.put]
     namespace std {
       template <class charT,
                 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, bool intl, ios_base& f,
                       char_type fill, long double units) const;
         iter_type put(iter_type s, bool intl, ios_base& f,
                       char_type fill, const string_type& digits) const;
         static locale::id id;

  _________________________
  19) The semantics here are different from ct.narrow.

       protected:
        ~money_put();                // virtual
         virtual iter_type
           do_put(iter_type, bool, ios_base&, char_type fill,
                  long double units) const;
         virtual iter_type
           do_put(iter_type, bool, 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, bool intl, ios_base& f, char_type fill,
                   long double quant) const;
     iter_type put(iter_type s, bool intl, ios_base& f, char_type fill,
                   const string_type& quant) const;
1 Returns:
    do_put(s, intl, f, loc, quant)

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

     iter_type do_put(iter_type s, bool intl, ios_base& str,
                      char_type fill, long double units) const;
     iter_type do_put(iter_type s, bool intl, ios_base& str,
                      char_type fill, const string_type& digits) const;
1 Effects:
    Writes characters to s  according  to  the  format  specified  by  a
    moneypunct<charT, Intl> facet reference mp and the character mapping
    specified by a ctype<charT> facet reference  ct  obtained  from  the
    locale  returned  by  str.getloc(),  and  str.flags().  The argument
    units is transformed into a sequence of wide characters as if by
       ct.widen(buf1, buf1 + sprintf(buf1, "%.01f", units), buf2)
    for character buffers buf1 and buf2.  If the first character in dig-
    its  or  buf2  is  equal to ct.widen('-'), then the pattern used for
    formatting is the result of mp.neg_format(); otherwise  the  pattern
    is  the  result  of  mp.pos_format().  Digit characters are written,
    interspersed with any thousands separators and decimal point  speci-
    fied  by  the  format,  in the order they appear (after the optional
    leading minus sign) in digits or buf2.  In digits, only the optional
    leading  minus  sign and the immediately subsequent digit characters
    (as classified according to ct) are used;  any  trailing  characters
    (including   digits  appearing  after  a  non-digit  character)  are
    ignored.  Calls str.width(0).
2 Notes:
    The currency symbol is generated  if  and  only  if  (str.flags()  &
    str.showbase) is nonzero.  If the number of characters generated for
    the specified format is less than the value returned by  str.width()
    on entry to the function, then copies of fill are inserted as neces-
    sary to pad to the specified width.   For  the  value  af  equal  to
    (str.flags()  &  str.adjustfield),  if (af == str.internal) is true,
    the fill characters are placed where none or space  appears  in  the
    formatting  pattern; otherwise if (af == str.left) is true, they are

    placed after the other characters; otherwise, they are placed before
    the other characters.  [Note: It is possible, with some combinations
    of format patterns and flag values, to produce output that cannot be
    parsed using num_get<>::get.   --end note]
3 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;
       };
     }
  The moneypunct<> facet defines monetary formatting parameters used  by
  money_get<>  and money_put<>.  A monetary format is a sequence of four
  components, specified by a pattern value p, such that the  part  value
  static_cast<part>(p.field[i])  determines  the  ith  component  of the
  format20)  In the field member of a pattern object, each value symbol,
  _________________________
  20) An array of char, rather than an array of part, is  specified  for
  pattern::field purely for efficiency.

  sign, value, and either space or none appears exactly once.  The value
  none, if present, is not first; the value space, if present,  is  nei-
  ther first nor last.

1 Where  none  or space appears, white space is permitted in the format,
  except where none appears at the end, in which case no white space  is
  permitted.   The  value  space  indicates  that  at least one space is
  required at that position.  Where  symbol  appears,  the  sequence  of
  characters   returned  by  curr_symbol()  is  permitted,  and  can  be
  required.  Where sign appears, the first (if any) of the  sequence  of
  characters  returned  by  positive_sign()  or negative_sign() (respec-
  tively as the monetary value is non-negative or negative) is required.
  Any  remaining  characters of the sign sequence are required after all
  other format components.  Where value appears,  the  absolute  numeric
  monetary value is required.

2 The format of the numeric monetary value is a decimal number:
       value ::= units [ decimal-point [ digits]] |
         decimal-point digits
  If frac_digits() returns a positive value, or
       value ::= units
  otherwise.   The symbol decimal-point indicates the character returned
  by decimal_point().  The other symbols are defined as follows:
       units ::= digits [ thousands-sep units ]
       digits ::= adigit [ digits ]
  In the syntax specification, the symbol adigit is any  of  the  values
  ct.widen(c) for c in the range '0' through '9', inclusive, and ct is a
  reference of type const ctype<charT>& obtained  as  described  in  the
  definitions  of money_get<> and money_put<>.  The symbol thousands-sep
  is the character returned by  thousands_sep().   The  space  character
  used  is  the  value  ct.widen(' ').  White space characters are those
  characters c for which ci.is(space, c) returns true.   The  number  of
  digits  required after the decimal point (if any) is exactly the value
  returned by frac_digits().

3 The placement of thousands-separator characters (if any) is determined
  by the value returned by grouping(), defined identically as the member
  numpunct<>::do_grouping().

  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;
1 Returns:
    The radix separator to use in case do_frac_digits() is greater  than
    zero.21)

     charT do_thousands_sep() const;
2 Returns:
    The  digit  group separator to use in case do_grouping() specifies a
    digit grouping pattern.22)

     string       do_grouping() const;
3 Returns:
    A    pattern    defined    identically    as    the    result     of
    numpunct<charT>::do_grouping().23)

     string_type do_curr_symbol() const;
4 Returns:
    A string to use as the currency identifier symbol.24)

     string_type do_positive_sign() const;
     string_type do_negative_sign() const;
5 Returns:
    do_positive_sign()  returns the string to use to indicate a positive
    monetary value;25) do_negative_sign() returns the string to  use  to
    indicate a negative value.

     int do_frac_digits() const;
6 Returns:
    The number of digits after the decimal radix separator, if any.26)

     pattern do_pos_format() const;
     pattern do_neg_format() const;
7 Returns:
    The  instantiations  required  in  Table  2 (_lib.locale.category_),
    namely moneypunct<char>, moneypunct<wchar_t>, moneypunct<char,true>,
    and  moneypunct<wchar_t,true>, return an object of type pattern ini-
    tialized to { symbol, sign, none, value }.27)

  _________________________
  21) In common U.S. locales this is '.'.
  22) In common U.S. locales this is ','.
  23) This is most commonly the value "\003" not "3").
  24)  For international instantiations (second template parameter true)
  this is always four characters  long,  usually  three  letters  and  a
  space.
  25) This is usually the empty string.
  26) In common U.S. locales, this is 2.
  27) Note that the international symbol returned by do_curr_sym()  usu-
  ally contains a space, itself; for example, "USD ".

  22.2.6.4  Template class                [lib.locale.moneypunct.byname]
       moneypunct_byname
     namespace std {
       template <class charT, bool Intl = false>
       class moneypunct_byname : public moneypunct<charT, Intl> {
       public:
         typedef money_base::pattern pattern;
         typedef basic_string<charT> string_type;

         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;
1 Returns:
    do_open(name, loc).

     string_type get(catalog cat, int set, int msgid,
                     const string_type& dfault) const;
2 Returns:
    do_get(cat, set, msgid, dfault).

     void  close(catalog cat) const;
3 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;
1 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.
2 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;
3 Requires:
    A catalog cat obtained from open() and not yet closed.
4 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;
5 Requires:
    A catalog cat obtained from open() and not yet closed.

6 Effects:
    Releases unspecified resources associated with  cat.
7 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:
         typedef messages_base::catalog catalog;
         typedef basic_string<charT>    string_type;

         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
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
                                             // imbue it on all the std streams
         cin.imbue(locale());
         cout.imbue(locale());
         cerr.imbue(locale());
         wcin.imbue(locale());
         wcout.imbue(locale());
         wcerr.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(s);
         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:
       // file: 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 13):

                   Table 13--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 header <locale.h>.

  SEE ALSO: ISO C clause 7.4.