      ______________________________________________________________________

      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 {
      // subclause _lib.locale_, locale:
        class locale;
        template <class Facet> const Facet& use_facet(const locale&);
        template <class Facet> bool         has_facet(const locale&) throw();

      // subclause _lib.locale.convenience_, convenience interfaces:
        template <class charT> bool isspace (charT c, const locale& loc) const;
        template <class charT> bool isprint (charT c, const locale& loc) const;
        template <class charT> bool iscntrl (charT c, const locale& loc) const;
        template <class charT> bool isupper (charT c, const locale& loc) const;
        template <class charT> bool islower (charT c, const locale& loc) const;
        template <class charT> bool isalpha (charT c, const locale& loc) const;
        template <class charT> bool isdigit (charT c, const locale& loc) const;
        template <class charT> bool ispunct (charT c, const locale& loc) const;
        template <class charT> bool isxdigit(charT c, const locale& loc) const;
        template <class charT> bool isalnum (charT c, const locale& loc) const;
        template <class charT> bool isgraph (charT c, const locale& loc) const;
        template <class charT> charT toupper(charT c, const locale& loc) const;
        template <class charT> charT tolower(charT c, const locale& loc) const;
      // subclauses _lib.category.ctype_ and _lib.facet.ctype.special_, ctype:
        class ctype_base;
        template <class charT> class ctype;
        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;
      // subclauses _lib.category.numeric_ and _lib.facet.numpunct_, numeric:
        template <class charT, class InputIterator>  class num_get;
        template <class charT, class OutputIterator> class num_put;
        template <class charT> class numpunct;
        template <class charT> class numpunct_byname;
      // subclause _lib.category.collate_, collation:
        template <class charT> class collate;
        template <class charT> class collate_byname;
      // subclause _lib.category.time_, date and time:
        class time_base;
        template <class charT, class InputIterator>  class time_get;
        template <class charT, class InputIterator>  class time_get_byname;
        template <class charT, class OutputIterator> class time_put;
        template <class charT, class OutputIterator> class time_put_byname;
      // subclauses _lib.category.monetary_, money:
        class money_base;
        template <class charT, class InputIterator>  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;
      // subclause _lib.category.messages_, message retrieval:
        class messages_base;
        template <class charT> class messages;
        template <class charT> class messages_byname;
      }

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

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

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

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

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

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

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

      --A   member   operator   template    operator()(basic_string<C,T,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_put<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<char,InputIterator>,                      |
         |           money_get<wchar_t,InputIterator>,                   |
         |           money_put<char,OutputIterator>,                     |
         |           money_put<wchar_t,OutputIterator>                   |
         +---------------------------------------------------------------+
         |numeric    numpunct_byname<char>, numpunct_byname<wchar_t>     |
         |           num_get<C,InputIterator>, num_put<C,OutputIterator> |
         +---------------------------------------------------------------+
         |time       time_get<char,InputIterator>,                       |
         |           time_get_byname<char,InputIterator>,                |
         |           time_get<wchar_t,OutputIterator>,                   |
         |           time_get_byname<wchar_t,OutputIterator>,            |
         |           time_put<char,OutputIterator>,                      |
         |           time_put_byname<char,OutputIterator>,               |
         |           time_put<wchar_t,OutputIterator>                    |
         |           time_put_byname<wchar_t,OutputIterator>             |
         +---------------------------------------------------------------+

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

    6 In declarations of facets,  a  template  formal  parameter  with  name
      InputIterator  or  OutputIterator  indicates  the  set of all possible
      instantiations on parameters that satisfy the requirements of an Input
      Iterator  or  an Output Iterator, respectively (_lib.iterator.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 declaration as fol-
      lows:
            static ::std::locale::id id;
      Template parameters in this Clause which  must  be  facets  are  those
      named Facet in declarations.  A program that passes a type that is not
      a facet, as an (explicit or deduced) template parameter  to  a  locale
      function expecting a facet, is ill-formed.

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

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

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

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

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

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

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

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

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

      locale() throw();

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

      locale(const locale& other) throw();

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

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

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

      explicit locale(const char* std_name);

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

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

      Effects:
        Constructs a locale as a copy of other except for the facets identi-
        fied  by  the  category  argument,  which instead implement the same
        semantics as locale(std_name).
      Throws:
        runtime_error if the argument is not valid, or is null.
      Notes:
        The locale has a name if and only if other has a name.

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

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

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

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

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

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

      ~locale() throw();

    2 A non-virtual destructor that throws no exceptions.

      22.1.1.3  locale members                          [lib.locale.members]

      basic_string<char>  name() const;

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

      22.1.1.4  locale operators                      [lib.locale.operators]

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

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

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

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

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

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

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

      22.1.1.5  locale static members                   [lib.locale.statics]

      static locale global(const locale& loc);

    1 Sets the global locale to its argument.

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

      static const locale& classic();

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

      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.
      Returns:
        a reference to the corresponding facet of loc, if present.
      Throws:
        bad_cast if has_facet<Facet>(*this) is false.
      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();

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

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

      22.1.3.2  Character conversions                      [lib.conversions]

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

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

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

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

      22.2  Standard locale categories               [lib.locale.categories]

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

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

    1 The type mask is a bitmask type.

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

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

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

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

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

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

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

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

      Returns:
        do_scan_is(m,low,high)

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

      Returns:
        do_scan_not(m,low,high)

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

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

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

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

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

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

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

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

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

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

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

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

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

        would return true; otherwise, returns high.

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

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

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

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

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

      Effects:
        Converts a character or characters to 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.
      Returns:
        The first form returns the corresponding lower-case character if  it
        is  known to exist, or its argument if not.  The second form returns
        high.

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

      Effects:
        Applies the simplest reasonable transformation from a char value  or
        sequence  of  char  values  to  the  corresponding  charT  value  or
        values.4)  The  only characters for which unique transformations are
        required   are   those   in   the   basic   source   character   set
      _________________________
      4) The char argument of do_widen is intended to accept values  derived
      from character literals for conversion the locale's encoding.

        (_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.5)
        The second form transforms each character  *p  in  the  range  [low,
        high), placing the result in dest[p-low].
      Returns:
        The  first  form  returns  the  transformed  value.  The second form
        returns high.

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

      Effects:
        Applies the simplest reasonable transformation from a charT value or
        sequence  of charT values to the corresponding char value or values.
        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
        (or dfault if no  simple  transformation  is  readly  available)  in
        dest[p-low].
      Returns:
        The  first  form returns the transformed value; or dfault if no map-
        ping is readily available.  The second form returns high.

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

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

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

      22.2.1.3  ctype specializations              [lib.facet.ctype.special]
      namespace std {
        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) const;
          virtual const char* do_toupper(char* low, const char* high) const;
          virtual char        do_tolower(char) const;
          virtual const char* do_tolower(char* low, const char* high) const;
        };
      }

    1 A specialization ctype<char> is provided so that the member  functions
      on type char can be implemented inline.6)  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();

      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);

      Precondition:
        tbl either 0 or an array of at least table_size elements.
      Effects:
        Passes its refs argument to its base class constructor.

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

      Effects:
        The second form, for all *p in the range [low, high), assigns vec[p-
        low] to table()[(unsigned char)*p].
      Returns:
        The first form returns table()[(unsigned char)c]  &  m;  the  second
      _________________________
      6) Only the char (not unsigned char and signed char) form is provided.
      The specialization is specified in the standard, and not  left  as  an
      implementation detail, because it affects the derivation interface for
      ctype<char>.

        form returns high.

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

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

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

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

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

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

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

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

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

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

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

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

      const mask* table() const throw();

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

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

      static const mask* classic_table() throw();

      Returns:
        A  pointer  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;

      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>
        template <> class ctype_byname<char> : public ctype<charT> {
        public:
          explicit ctype_byname(const char*, size_t refs = 0);
        protected:
         ~ctype_byname();  // virtual
          virtual char        do_toupper(char) const;
          virtual const char* do_toupper(char* low, const char* high) const;
          virtual char        do_tolower(char) const;
          virtual const char* do_tolower(char* low, const char* high) const;
        };
      }

    1
      22.2.1.5  Template class codecvt                  [lib.locale.codecvt]

      namespace std {
        class codecvt_base {
        public:
          enum result { ok, partial, error, noconv };
        };
        template <class 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_unshift(stateT& state,
                  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 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 Implementations   are   required   to   provide   instantiations   for
      <wchar_t,char,mbstate_t>  and  <char,char,mbstate_t>.   The base class
      instance of the latter implements a degenerate conversion: its  member
      always_noconv()    returns    true   and   max_length()   returns   1.

      Instantiations on mbstate_t perform conversion between encodings known
      to  the library implementor.  Other encodings can be converted by spe-
      cializing on a user-defined stateT type.  The stateT object  can  con-
      tain  any  state that is useful to communicate to or from the special-
      ized do_convert member.  The base class  implementations  convert  the
      implementation-defined native execution codeset.

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

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

      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;

      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;

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

      int encoding() const throw();

      Returns:
        do_encoding()

      bool always_noconv() const throw();

      Returns:
        do_always_noconv()

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

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

      int max_length() const throw();

      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;

      Preconditions:
        (from<=from_end && to<=to_end) well-defined and true; state initial-
        ized, if at the beginning of a sequence, or else equal to the result
        of converting the preceding characters in the sequence.
      Effects:
        Translates characters in the 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]
      Notes:
        Its operations on state are unspecified.
        [Note:  This  argument  can  be used, for example, to maintain shift
        state, to specify conversion options (such as  count  only),  or  to
        identify a cache of seek offsets.   --end note]
      Returns:
        An enumeration value, as summarized in Table 4:

                           Table 4--convert result values

         +-----------------------------------------------------------------+
         | Value                           Meaning                         |
         +-----------------------------------------------------------------+
         |ok        completed the conversion                               |
         |partial   not all source characters converted                    |
         |error     encountered a from_type character it could not convert |
         |noconv    no conversion was needed                               |
         +-----------------------------------------------------------------+
        A  return value of partial, if (from_next==from_end), indicates that
        either the destination sequence has not absorbed all  the  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;

      Effects
        Places characters starting at to that should be appended  to  termi-
        nate  a  sequence  when  the current stateT is given by state.7) The
        base class implementation stores no characters.
      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                |
       +----------------------------------------------------------------------+
        The base class implementation returns noconv.

      int do_encoding() const throw();

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

      bool do_always_noconv() const throw();

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

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

      _________________________
      7) Typically these will be characters to return the state to stateT()
      8) 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.

      Preconditions:
        (from<=from_end) well-defined and true; state initialized, if at the
        beginning of a sequence, or else equal to the result  of  converting
        the preceding characters in the sequence.
      Returns:
        (from_next-from)  where  from_next is the largest value in the range
        [from,from_end] such that  the  sequence  of  values  in  the  range
        [from,from_next)  represents  max or fewer valid complete characters
        of type internT.  The base class implementation returns  the  lesser
        of max and (from_end-from).

      int do_max_length() const throw();

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

      22.2.1.6  Template class                   [lib.locale.codecvt.byname]
           codecvt_byname
      namespace std {
        template <class 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 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();
        };
      }

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

      _________________________
      9) Parsing "-1" correctly into (e.g.) an unsigned short requires  that
      the  corresponding member get() at least extract the sign before dele-
      gating.

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

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

      22.2.2.1  Template class num_get                  [lib.locale.num.get]
      namespace std {
        template <class charT, class InputIterator = istreambuf_iterator<charT> >
        class num_get : public locale::facet {
        public:
          typedef charT            char_type;
          typedef InputIterator    iter_type;
          explicit num_get(size_t refs = 0);
          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;

      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;

      Effects:
        Reads   characters   from   in,   interpreting   them  according  to
        str.flags(),  use_facet<   ctype<charT>   >(loc),   and   use_facet<
        numpunct<charT>  >(loc).  If an error occurs, val is unchanged; oth-
        erwise it is set to the resulting value.

    1 The details of this operation occur in two stages

      --Stage 1: Determine a conversion specifier

      --Stage 2: Extract characters from in and transform them into  char's,
        converting the value transformed characters according to the conver-
        sion specification determined in stage 1.

      --Stage 3: Store results
        The details of the stages are presented below.
      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 basefield = (flags & ios_base::basefield);
              fmtflags boolalpha = (flags & ios_base::boolalpha);
        For conversion to an integral  type,  the  function  determines  the
        integral conversion specifier as indicated in Table 6:

                            Table 6--Integer conversions

                +--------------------------------------------------+
                |            State                stdio equivalent |
                +--------------------------------------------------+
                |basefield == oct                        %o        |
                +--------------------------------------------------+
                |basefield == hex && !uppercase          %x        |
                +--------------------------------------------------+
                |basefield == hex                        %X        |
                +--------------------------------------------------+
                |basefield == 0                          %i        |
                +--------------------------------------------------+
                |signed integral type                    %d        |
                +--------------------------------------------------+
                |unsigned integral type                  %u        |
                +--------------------------------------------------+
        For conversions to a  floating type the specifier is %g.
        For conversions to void* the specifier is %p.
         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        |
                         +---------------------------------+
      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 = use_facet<ctype<charT> >(loc).narrow(ct,' ');
              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 );

        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.
         If  the  character  is neither discarded nor accumulated then in is
        advanced by ++in and processing returns to the beginning of stage 2.
      Stage 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 std::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
        Digit grouping is checked.  That is, the positions of discarded sep-
        arators is examined for consistency  with  use_facet<numpunct<charT>
        >(loc).grouping()  If they are not consistent then ios_base::failbit
        is assigned to err.

    2 In 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;

      Effects:
        If  (str.flags()&&ios_base::boolalpha)==0  then input proceeds as it
        would for an int 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.

    3 Otherwise 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).

    4 As  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.
      Returns:
        in.

      22.2.2.2  Template class num_put                  [lib.locale.num.put]
      namespace std {
        template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
        class num_put : public locale::facet {
        public:
          typedef charT            char_type;
          typedef OutputIterator   iter_type;
          explicit num_put(size_t refs = 0);
          iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const;
          iter_type put(iter_type s, ios_base& f, char_type fill, long v) const;
          iter_type put(iter_type s, ios_base& f, char_type fill,
                        unsigned long v) const;
          iter_type put(iter_type s, ios_base& f, char_type fill,
                        double v) const;
          iter_type put(iter_type s, ios_base& f, char_type fill,
                        long double v) const;
          iter_type put(iter_type s, ios_base& f, char_type fill,
                        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,
                                   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,
                    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,
                    void* val) const;

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

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

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

      Effects:
        Writes characters to the sequence out, formatting val as desired. In
        the following description, a local variable initialized with
              locale loc = str.getloc();
        The base class implementation is described 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
              std::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.
        Detailed descriptions of each stage follow.
      Returns:
        out.

      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 = this->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));

        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.
        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        |
          +---------------------------------------------------------------+
        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        |
        +--------------------------------------------------------------------+
         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 |
                         +---------------------------------+
                         |short                   h        |
                         +---------------------------------+
                         |unsigned short          h        |
                         +---------------------------------+
                         |long                    l        |
                         +---------------------------------+
                         |unsigned long           l        |
                         +---------------------------------+
                         |long double             L        |
                         +---------------------------------+
                         |otherwise             none       |
                         +---------------------------------+
        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 oth-   flags & showpos             +         |
          |er than a character     flags & showbase            #         |
          |type                                                          |
          +--------------------------------------------------------------+
          |a floating-point type   flags & showpos             +         |
          |                        flags & showpoint           #         |
          +--------------------------------------------------------------+
        For conversion from a floating-point type, if (flags() & fixed) != 0
        or if precision() > 0, then precision() is specified in the  conver-
        sion specification.
        For conversion from void* the specifier is %p.
         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.

      Stage 2:
        Any  character  c  other  than  a decimal point(.) is converted to a
        charT via charT(c)

    1 A local variable punct is initialized via
          numpunct<charT> punct = use_facet< numpunct<charT> >(str.getloc())
        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_
        Decimal point characters(.) are replaced by punct.decimal_point()

      Stage 3:
        A local variable is initialized as
              fmtflags adjustfield=   (flags & (ios_base::adjustfield));
        The location of any padding 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 stage 2 sequence |
           +-------------------------------------------------------------+
        width() is nonzero and the number of charT's in the  sequence  after
        stage  3 is less than width(), then enough fill characters are added
        to the sequence at the position indicated for padding to  bring  the
        length of the sequence to width().
        width(0) is called.

      Stage 4:
        The sequence of charT's at the end of stage 3 are output via
              *out++ = c
        If  at  any  point  out.failed() becomes true, then output is termi-
        nated.

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

      Effects:
        If (str.flags()&ios_base::boolalpha)==0 then do
              out = put(out, str, fill, (int)val)
      _________________________
      10) The conversion specification #o generates a leading 0 which is not
      a padding character.

        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.

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

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

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

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

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

      char_type decimal_point() const;

      Returns:
        do_decimal_point()

      char_type thousands_sep() const;

      Returns:
        do_thousands_sep()

      string grouping()  const;

      Returns:
        do_grouping()

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

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

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

      char_type do_decimal_point() const;

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

      string_type do_thousands_sep() const;

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

      string do_grouping() const;

      Returns:
        A  basic_string<char>  vec  used  as  a vector of integer values, in
        which  each element vec[i] represents the number of digits11) in the
      _________________________
      11) Thus, the string "\003" specifies groups of 3 digits each, and "3"
      probably indicates groups of 51 (!) digits each.

        group at position i, starting  with  position  0  as  the  rightmost
        group.   If  vec.size() <= i, the number is the same as group (i-1);
        if (i<0 || vec[i]<=0 || vec[i]==CHAR_MAX), the  size  of  the  digit
        group is unlimited.
        The  base  class implementation returns the empty string, indicating
        no grouping.

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

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

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

      22.2.4  The collate category                    [lib.category.collate]

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

        protected:
         ~collate();  // virtual
          virtual int    do_compare(const charT* low1, const charT* high1,
                                    const charT* low2, const charT* high2) const;
          virtual string_type do_transform(const charT* low, const charT* high) const;
          virtual long   do_hash     (const charT* low, const charT* high) const;
        };
      }

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

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

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

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

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

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

      Returns:
        do_transform(low, high)

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

      Returns:
        do_hash(low, high)

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

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

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

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

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

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

      Returns:
        An  integer value equal to the result of calling hash() on any other
        string for which do_compare() returns 0 (equal) when passed the  two
        strings.   [Note:  The  probability  that the result equals that for
        another string which does not compare equal should  be  very  small,
        approaching   (1.0/numeric_limits<unsigned  long>::max()).     --end
        note]

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

      22.2.5  The time category                          [lib.category.time]

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

      22.2.5.1  Template class time_get                [lib.locale.time.get]

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

      namespace std {
        class time_base {
        public:
          enum dateorder { no_order, dmy, mdy, ymd, ydm };
        };

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

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

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

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

      dateorder date_order() const;

      Returns:
        do_date_order()

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

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

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

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

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

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

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

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

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

      dateorder do_date_order() const;

      Returns:
        An enumeration value indicating the preferred  order  of  components
        for those date formats that are composed of day, month, and year.14)
        Returns  no_order if the date format specified by 'x' contains other
      _________________________
      14)  This  function is intended as a convenience only, for common for-
      mats, and may return no_order in valid locales.

        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;

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

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

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

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

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

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

      Effects:
        Reads characters starting at s until it has extracted an unambiguous
        year identifier.  It  is  implementation-defined  whether  two-digit
        year numbers are accepted, and (if so) what century they are assumed
        to lie in.  Sets the t->tm_year member accordingly.

      Returns:
        An iterator pointing immediately beyond the  last  character  recog-
        nized as part of a valid year identifier.

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

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

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

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

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

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

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

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

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

      _________________________
      15) Interpretation of the modifier argument is implementation-defined,
      but should follow POSIX conventions.

      22.2.6  The monetary category                  [lib.category.monetary]

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

    2 money_get<>    and    money_put<>   members   use   their   ios_base&,
      ios_base::iostate&,   and   fill    arguments    as    described    in
      (_lib.locale.categories_), and the moneypunct<> and ctype<> facets, to
      determine formatting details.

      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 const bool intl = Intl;
          static locale::id id;
        protected:
         ~money_get();  // virtual
          virtual iter_type do_get(iter_type, bool, iter_type, ios_base&,
                                   ios_base::iostate& err, long double& units) const;
          virtual iter_type do_get(iter_type, bool, iter_type, ios_base&,
                                   ios_base::iostate& err, string_type& digits) const;
        };
      }

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

      iter_type get(iter_type s, iter_type end, 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;

      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& strfP, ios_base::iostate& err,
                       string_type& digits) const;

      Effects:
        Reads  characters  from s until it has constructed a monetary value,
        as specified in str.flags() and the moneypunct<charT,true> or money-
        punct<charT,false> facet of str.getloc(), (depending on whether intl
        is true or false respectively) or until it encounters  an  error  or
        runs  out of characters.  It parses the format sequence specified by
        moneypunct<>::neg_format() for all monetary values.  The result is a
        pure  sequence  of digits, representing a count of the smallest unit
        of currency representable.16)
        Digit  group  separators are optional; if present, digit grouping is
        checked after all syntactic elements have been read.  If no grouping
        is  specified, any thousands separator characters encountered in the
        input sequence are not considered part of the numeric format.
        Where space or none appear in the format pattern, except at the end,
        optional  whitespace is consumed.  If (str.flags() & ios_base::show-
        base) is false, the currency symbol is optional, and if  it  appears
        after  all other required syntactic elements it is not consumed.  If
        the expression above is true, the currency symbol is  required,  and
        is always consumed.  If the first character of the a sign appears in
        its correct position, any remaining sign  characters  are  required,
        and  consumed.   [Example: If showbase is off, then when the sign is
        "()" and the currency symbol is "L", in "(100 L)" the  "L"  is  con-
        sumed; but in "-100 L" it is not.   --end example] Sets the argument
        units or digits  from  the  sequence  of  digits  found.   units  is
        negated,  or  digits  is  preceded by '-', for a negative value.  On
        error, the units or digits argument is unchanged.
      Returns:
        An iterator pointing immediately beyond the  last  character  recog-
        nized as part of a valid monetary quantity.

      22.2.6.2  Template class money_put              [lib.locale.money.put]

      _________________________
      16) For  example, the sequence $1,056.23 in a common U.S. locale would
      yield, for units, 105623, or for digits, 105623".

      namespace std {
        template <class charT, bool Intl = false,
                  class OutputIterator = ostreambuf_iterator<charT> >
        class money_put : public locale::facet {
        public:
          typedef charT               char_type;
          typedef OutputIterator      iter_type;
          typedef basic_string<charT> string_type;
          explicit money_put(size_t refs = 0);
          iter_type put(iter_type s, 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;
        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;

      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;

      Effects:
        Writes characters to s, according to the  format  specified  by  the
        moneypunct<charT,true>   or  moneypunch<charT,false>  facet  of  loc
        (depending on whether intl  is  true  or  false  respectively),  and
        str.flags().   Ignores  any fractional part of units, or any charac-
        ters in digits beyond the (optional)  leading  '-'  and  immediately
        subsequent digits.

      Notes:
        The   currency   symbol   is   generated   only  if  (str.flags()  &
        ios_type::showbase) is true.  If ((str.flags()  &  ios_type::adjust-
        field)  ==  ios_type::internal) the fill characters are placed where
        none or space appears in the formatting pattern (_lib.money.get.vir-
        tuals_).
      Returns:
        An  iterator pointing immediately after the last character produced.

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

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

    1 This  provides  money  punctuation,  similar   to   numpunct<>   above
      (_lib.locale.numpunct_).  In particular, the value portion of the for-
      mat is:
        value ::= units [decimal-point [digits]] |
                  decimal-point digits
      if frac_digits returns a positive value, or just

        value ::= units
      otherwise.  In these forms, the decimal-point and  thousands-separator
      are  as  determined  below  and the number of digits after the decimal
      point is exactly the value returned by frac_digits.

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

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

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

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

      charT do_decimal_point() const;

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

      charT do_thousands_sep() const;

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

      string       do_grouping() const;

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

      string_type do_curr_symbol() const;
      _________________________
      17) In common U.S. locales this is '.'.
      18) In common U.S. locales this is ','.
      19) This is most commonly the value "\003" not "3").

      Returns:
        A string to use as the currency identifier symbol.20)

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

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

      int do_frac_digits() const;

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

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

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

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

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

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

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

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

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

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

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

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

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

      Returns:
        do_open(name, loc).

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

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

      void  close(catalog cat) const;

      Effects:
        Calls do_close(cat).

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

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

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

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

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

      void do_close(catalog cat) const;

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

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

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

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

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

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

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

    5 [Example: Traditional global localization is still easy:

        #include <iostream>
        #include <locale>
        int main(int argc, char** argv)
        {
          using namespace std;
          locale::global(locale(""));  // set the global locale
            // 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;
          if (cerberos) {
            ios_base::iostate err = goodbit;
            struct tm t;
            use_facet< time_get<char> >(s.getloc()).get_date(s, 0, s, err, &t);
            if (!err) d = Date(t.tm_day, t.tm_mon + 1, t.tm_year + 1900);
            s.setstate(err);
          }
          return s;
        }
       --end example]

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

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

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

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

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

      22.3  C Library Locales                                [lib.c.locales]

    1 Header <clocale> (Table 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.