______________________________________________________________________

  22   Localization library                 [lib.localization]

  ______________________________________________________________________

1 This clause describes components that C++ programs may use to  perform
  localization  of strings.  The locale facility includes international­
  ization support for character classification  and  collation,  numeric
  and  currency  punctuation,  date  and  time  formatting,  and message
  retrieval.

2 The   following   subclauses   describe   components    for    locales
  (_lib.locales_),  standard  facets  (_lib.std.facets_), and facilities
  included from the ISO C library (_lib.c.locales_).

  22.1  Locales                                            [lib.locales]

1 Headers:

  --<locale>

2 Table 1:

                    Table 1--Header <locale> synopsis

  +--------------------------------------------------------------------------+
  |          Type                                 Name(s)                    |
  +--------------------------------------------------------------------------+
  |Template classes:                                                         |
  |locale::codecvt             locale::msg                                   |
  |locale::codecvt_byname      locale::msg_byname                            |
  |locale::collate             locale::numpunct                              |
  |locale::collate_byname      locale::num_get                               |
  |locale::ctype               locale::num_put                               |
  |locale::ctype_byname        locale::time_get                              |
  |locale::moneypunct          locale::time_get_byname                       |
  |locale::moneypunct_byname   locale::time_put                              |
  |locale::money_get           locale::time_put_byname                       |
  |locale::money_put                                                         |
  +--------------------------------------------------------------------------+
  |Classes:                    locale                    locale::ctype<char> |
  +--------------------------------------------------------------------------+
  |Struct:                     locale::ctype_base                            |
  +--------------------------------------------------------------------------+
  |Operator functions:         operator<< (locale)       operator>> (locale) |
  +--------------------------------------------------------------------------+

3 The header <locale> defines classes and several functions that  encap­
  sulate and manipulate the information peculiar to a locale.1)

  22.1.1  Class locale                                      [lib.locale]
  class locale {
  public:
    class id;
    class facet;
    class ctype_base;
    template <class charT> class ctype;
                           class ctype<char>;        // specialization
    template <class charT> class ctype_byname;
                           class ctype_byname<char>; // specialization
    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;
    template <class charT> class collate;
    template <class charT> class collate_byname;
    template <class fromT, class toT, class stateT> class codecvt;
    template <class fromT, class toT, class stateT> class codecvt_byname;
    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;
    template <class charT, class InputIterator> class money_get;
    template <class charT, class OutputIterator> class money_put;
    template <class charT> class moneypunct;
    template <class charT> class moneypunct_byname;
    template <class charT> class msg;
    template <class charT> class msg_byname;
    // member function template use<Facet>() returns a reference to
    // a facet.  Its result is guaranteed by locale's value semantics
    // to last at least as long as the locale it came from.  If the
    // facet requested is not present in *this, it returns the facet
    // from the current global locale, if present, or throws an exception.

    template <class Facet>
    const Facet& use() const
    {
      int i = (const id&) Facet::id;    // verify is a locale::id.
      facet* f = (Facet*) 0;            // verify derived from facet.
      return static_cast<const Facet&>(
        (i < imp_->vec_.size() && (f = imp_->vec_[i])) ? *f : delegate(i));
    }

  _________________________
  1)  In  this  subclause, the type name struct tm is an incomplete type
  that is defined in <ctime>.

    // has<Facet>() simply reports whether a locale implements a particular
    //   facet.  If (loc.has<facet>() || locale().has<facet>()) is false,
    //   loc.use<facet>() would throw an exception.

    template <class Facet>
    bool has() const
    {
      facet* null = (Facet*) 0;          // verify derived from facet.
      size_t ix = (const id&) Facet::id; // verify is a locale::id.
      return (ix < imp_->vec_.size()) && imp_->vec_[ix];
    }
    const basic_string<char>& name() const { return imp_->name_; }

    bool operator==(const locale& other) const
    { return ((imp_ == other.imp_) ||
              (name() != "*" && name() == other.name()))
    }

    bool operator!=(const locale& other) const { return !(*this == other); }
    // convenience interfaces
    template <class charT> inline bool isspace(charT c) const;
    template <class charT> inline bool isprint(charT c) const;
    template <class charT> inline bool iscntrl(charT c) const;
    template <class charT> inline bool isupper(charT c) const;
    template <class charT> inline bool islower(charT c) const;
    template <class charT> inline bool isalpha(charT c) const;
    template <class charT> inline bool isdigit(charT c) const;
    template <class charT> inline bool ispunct(charT c) const;
    template <class charT> inline bool isxdigit(charT c) const;
    template <class charT> inline bool isalnum(charT c) const;
    template <class charT> inline bool isgraph(charT c) const;

    template <class charT> inline charT toupper(charT c) const;
    template <class charT> inline charT tolower(charT c) const;

    // this template function satisfies requirements for a
    //  comparator predicate template argument
    template <class charT>
    inline bool operator()(const basic_string<charT>& s1,
                           const basic_string<charT>& s2) const;

    //********** constructors ****************
    // default constructor: the current global locale
    locale() : imp_(global_ ? global_ : init()) { imp_->add_ref(); }

    locale(const locale& other)  { imp_ = other.imp_; imp_->add_ref(); }

    const locale& operator=(const locale& other) const
    {
      if (imp_ != other.imp_) {
        imp_->rem_ref(); imp_ = other.imp_; imp_->add_ref();
      }
      return *this;
    }

    // the following constructor makes a locale composed of "byname"
    //  facets, and assigns a name.

    locale(const char* std_name);  // using std C locale names, e.g. "POSIX"

    typedef unsigned category;  // as defined in <clocale>, e.g. LC_CTYPE

    // the following constructor copies its first argument except for a
    // specified component, which is constructed on the spot.  if *other*
    // has a name, the new locale does also.

    locale(const locale& other, const char* std_name, category);
    // the following constructor copies all facets but one from the first
    //  argument, installs the other argument as the remaining facet.
    //  The resulting locale has no name.

    template <class Facet>
    locale(const locale& other, Facet* f)  // to accrete or replace facet
    : imp_(new imp(*other.imp_, 1))
    {
      f->add_ref();
      install(f, Facet::id, "*");
    }

    // the following constructor copies all facets but one from the
    // first argument, and the remaining facet from the second argument.
    // The resulting locale has a name only if both argument locales do.

    template <class Facet>
    locale(const locale& other, const locale& one) // to replace a facet
    : imp_(new imp(*other.imp_, 1))
    {
      facet* f = (Facet*) one.imp_->vec[Facet::id];  // check derivation
      install(f, Facet::id, merge_names(Facet::id, one.imp_->name_));
    }

    ~locale() { imp_->rem_ref(); }  // non-virtual

    // static members:
    static locale global(const locale&);  // replaces ::setlocale(...)
    static const locale& classic();       // the "C" locale
    static const locale transparent()     // continuously updated global locale
      { return locale(new imp(1, 0, true)); }
  };
  template <class charT>
  basic_ostream<charT>& operator<<(basic_ostream<charT>& s, const locale& l)
    { s << l.name() << endl; return s;}

  template <class charT>
  basic_istream<charT>& operator>>(basic_istream<charT>& s, locale& l);
    // read a line, construct a locale, throw exception if cannot.

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

2 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.  Access to
  the  facets  of  a  locale  is  via  two  member  function  templates,
  locale::use<facet>() and locale::has<facet>().

3 For example, the standard iostream operator<< might be implemented as:
    ostream& operator<<(ostream& s, double f)
    {
      locale l = s.rdloc();
      if (s.opfx()) {
        l.use< locale::num_put<char> >().put(s, s, l, f);
        s.osfx();
      }
      return s;
    }
  In the call to l.use<...>(), the type argument chooses a facet, making
  available  all  members  of the named type.  If the named facet is not
  present in a locale (or, failing  that,  in  the  global  locale),  it
  throws  the  standard  exception  bad_cast.  You can check if a locale
  implements a particular  facet  with  the  member  has<...>().   User-
  defined  facets  may be bestowed on a locale, and used the same way as
  standard facets.

4 All locale semantics are accessed via use<>() and  has<>(),  with  two
  exceptions.   Convenient interfaces are provided for traditional ctype
  functions such as isdigit() and isspace(),  so  that  given  a  locale
  object loc you can say loc.isspace(c).  These are provided to ease the
  conversion of existing extractors.  Also, a member  template  function
  operator()(basic_string<T>&,  basic_string<T>&)  is provided so that a
  locale may be used as a predicate argument  to  the  standard  collec­
  tions.

5 The  static  member locale::global(), which returned a snapshot of the
  current  global  locale,  is  replaced  by  the  default   constructor
  locale(),  which  is  both  shorter to type and useful in more places.
  The static member locale::transparent(), and any locale  with  similar
  behavior,  is  now  documented  as  unsafe  to imbue on an iostream or
  install as the global locale; the effect is  undefined.   All  locales
  are  now  semi-transparent (translucent?), in that a locale which does
  not implement a facet delegates to the global locale.

  +-------                 BEGIN BOX 1                -------+
  Effects TBS:
  +-------                  END BOX 1                 -------+

  22.1.1.1  Type locale::category                  [lib.locale.category]
      typedef unsigned category;  // as defined in <clocale>, e.g. LC_CTYPE

  22.1.1.2  locale constructors                        [lib.locale.cons]
      locale();
      locale(const locale& other);
      const locale& operator=(const locale& other) const;
      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);

  22.1.1.3  locale destructor                           [lib.locale.des]
      ~locale();

  22.1.1.4  locale::use                                 [lib.locale.use]
      template <class Facet> const Facet& use() const;

  22.1.1.5  locale::has                                 [lib.locale.has]
      template <class Facet> bool has() const;

  22.1.1.6  locale::name                               [lib.locale.name]
      const basic_string<char>& name() const;

  22.1.1.7  locale::operator==                         [lib.locale.op==]
      bool operator==(const locale& other) const;

  22.1.1.8  locale::operator!=                         [lib.locale.op!=]
      bool operator!=(const locale& other) const;

  22.1.1.9  locale::isspace                         [lib.locale.isspace]
      template <class charT> bool isspace(charT c) const;

  22.1.1.10  locale::isprint                        [lib.locale.isprint]
      template <class charT> bool isprint(charT c) const;

  22.1.1.11  locale::iscntrl                        [lib.locale.iscntrl]
      template <class charT> bool iscntrl(charT c) const;

  22.1.1.12  locale::isupper                        [lib.locale.isupper]
      template <class charT> bool isupper(charT c) const;

  22.1.1.13  locale::islower                        [lib.locale.islower]
      template <class charT> bool islower(charT c) const;

  22.1.1.14  locale::isalpha                        [lib.locale.isalpha]
      template <class charT> bool isalpha(charT c) const;

  22.1.1.15  locale::isdigit                        [lib.locale.isdigit]
      template <class charT> bool isdigit(charT c) const;

  22.1.1.16  locale::ispunct                        [lib.locale.ispunct]
      template <class charT> bool ispunct(charT c) const;

  22.1.1.17  locale::isxdigit                      [lib.locale.isxdigit]
      template <class charT> bool isxdigit(charT c) const;

  22.1.1.18  locale::isalnum                        [lib.locale.isalnum]
      template <class charT> bool isalnum(charT c) const;

  22.1.1.19  locale::isgraph                        [lib.locale.isgraph]
      template <class charT> bool isgraph(charT c) const;

  22.1.1.20  locale::toupper                        [lib.locale.toupper]
      template <class charT> charT toupper(charT c) const;

  22.1.1.21  locale::tolower                        [lib.locale.tolower]
      template <class charT> charT tolower(charT c) const;

  22.1.1.22  locale::operator()                        [lib.locale.op()]
      template <class charT>
      bool operator()(const basic_string<charT>& s1,
                      const basic_string<charT>& s2) const;

  22.1.1.23  locale::global                          [lib.locale.global]
      static locale global(const locale&);

  22.1.1.24  locale::classic                        [lib.locale.classic]
      static const locale& classic();

  22.1.1.25  locale::transparent                [lib.locale.transparent]
      static const locale transparent();

  22.1.1.26  operator<<                                [lib.locale.op<<]
      template <class charT>
      basic_ostream<charT>& operator<<(basic_ostream<charT>& s, const locale& l)

  22.1.1.27  operator>>                                [lib.locale.op>>]
      template <class charT>
      basic_ostream<charT>& operator>>(basic_ostream<charT>& s, locale& l)

  22.1.2  Locale classes                            [lib.locale.classes]

1 For some standard facets there is a ``_byname'' class derived from  it
  that  implements POSIX locale semantics; they are specified by name in
  the standard to allow users to derive  from  them.   If  there  is  no
  ``_byname'' version, the base class implements POSIX semantics itself,
  sometimes with the help of another facet.

  22.1.2.1  Class locale::facet                       [lib.locale.facet]
    // locale::facet -- base class for locale feature sets.
    //   Any class deriving from facet must declare a *static* member:
    //      static std::locale::id id;
    class locale::facet {
      facet(const facet&);          // not defined
      void operator=(const facet&); // not defined
      void operator&() {}           // not usable

      size_t refcount_;
      //  MT environments must lock during add_ref() and rem_ref().
      void add_ref() { if (this) ++refcount_; }
      void rem_ref() { if (this && refcount_-- == 0) delete this; }
     protected:
      facet(size_t refs = 0) : refcount_(refs-1) { }
      virtual ~facet() {}

      friend class locale;
      friend class imp;
    };

  22.1.2.2  Class locale::id                       [lib.locale.ctype.id]
    // class id: identification of a locale facet interface,
    //  used as an index for lookup.

    class locale::id {
      void operator=(const id&); // not defined
      id(const id&);             // not defined
      void operator&() {}        // not usable

      mutable size_t id_;
      static size_t master_id_;  // init'd to 0 by loader
      void init()  //  MT environments must lock during this function.
        { if (!id_) id_ = ++master_id_; }
      operator size_t() const { return id_; }

     public:
      id() {}      // does *not* initialize member id_.
      friend class locale;
    };

  22.2  Standard locale facets                          [lib.std.facets]

  22.2.1  The ctype facet                              [lib.facet.ctype]

  22.2.1.1  Template class                       [lib.locale.ctype.base]
       locale::ctype_base
      struct locale::ctype_base : locale::facet {
        enum ctype {
          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=(1<<5)|(1<<6), GRAPH=(1<<7)|(1<<6)|(1<<5)
        };
       protected:
         ctype_base(size_t refs = 0) : facet(refs) {}
        ~ctype_base() {}
      };

  22.2.1.2  Template class locale::ctype              [lib.locale.ctype]
  template <class charT>
  class locale::ctype : public locale::facet {
  public:
    typedef charT char_type;
  protected:
    virtual bool do_is(ctype mask, charT c) const;
    virtual const charT* do_is(
              const charT* low, const charT* high, ctype* vec) const;
    virtual const char* do_scan_is(
              ctype mask, const charT* low, const charT* high) const;
    virtual const char* do_scan_not(
              ctype mask, 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* lo,
                                  const char* hi, charT* dest) const;
    virtual char         do_narrow(charT, char dfault) const;
    virtual const charT* do_narrow(const charT* lo, const charT* hi,
                                   char dfault, char* dest) const;

  public:
    bool         is(ctype mask, charT c) const
                   { return do_is(mask, c); }
    const charT* is(const charT* low, const charT* high, ctype* vec) const
                   { return do_is(low, high, vec); }
    const charT* scan_is(ctype mask, const charT* low, const charT* high) const
                   { return do_scan_is(mask, low, high); }
    const charT* scan_not(ctype mask, const charT* low, const charT* high) const
                   { return do_scan_not(mask, low, high); }

    charT        toupper(charT)               const;
                   { return do_toupper(c); }
    const charT* toupper(charT* low, const charT* high) const
                   { return do_toupper(low, high); }
    charT        tolower(charT c)               const;
                   { return do_tolower(c); }
    const charT* tolower(charT* low, const charT* high) const
                   { return do_tolower(low, high); }
    charT  widen(char c) const { return do_widen(c); }
    const char* widen(const char* lo, const char* hi, charT* to) const
             { return do_widen(lo, hi, to); }
    char   narrow(charT c, char dfault) const { return do_narrow(c, dfault); }
    const charT* narrow(const charT* lo, const charT*
                        char dfault, char* to) const
             { return do_narrow(lo, hi, dfault, to); }
    static locale::id id;

    ctype(size_t refs = 0) : locale::ctype_base(refs) {}
  protected:
    ~ctype() {}
  };
  template <class charT> locale::id locale::ctype<charT>::id;

1 Class locale::ctype encapsulates the C library <cctype> features.  The
  members of locale::ctype<charT> are much as in the previous  proposal,
  with the addition of the scan_is() and scan_not() functions which find
  the first character in a buffer that does or does not satisfy  a  bit­
  mask  criterion.   istream members are required to use locale::ctype<>
  for character classing.

2 A specialization locale::ctype<char> is provided, so that  the  member
  functions  on  type  char  may  be implemented inline.  Definitions of
  these functions have been provided for exposition.  Only the char, and
  not  the unsigned char and signed char forms, have been provided.  The
  specialization is specified in the standard (and not left as an imple­
  mentation  detail)  because  it  affects  the derivation interface for
  locale::ctype<char>.

  22.2.2  The ctype<char> facet                   [lib.facet.ctype.char]

  22.2.2.1  Class ctype<char>                    [lib.locale.ctype.char]
  // a specialization, so that char operations may be inline.
  // (We must specify this in the standard because it affects the
  //  derivation interface)

  class locale::ctype<char> : public locale::ctype_base {
  public:
    typedef char char_type;
   protected:
    const ctype* const table_;
    static const ctype classic_table_[UCHAR_MAX];
    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;
   public:
    bool is(ctype mask, char c) const
      { return table_[(unsigned char)c] & mask; }
    const char* is(const char* lo, const char* hi, ctype* vec) const
      { while (lo != hi) *vec++ = table_[(unsigned char)*lo++]; return lo; }
    const char* scan_is(ctype mask, const char* low, const char* high) const
    {
      while (low != high && !(table_[(unsigned char) *low++] & mask);
      return low;
    }
    const char* scan_not(ctype mask, const char* low, const char* high) const
    {
      while (low != high && (table_[(unsigned char)*low++] & mask);
      return low;
    }
    char        toupper(char c)               const;
                 { return do_toupper(c); }
    const char* toupper(char* low, const char* high) const
                 { return do_toupper(low, high); }
    char        tolower(char c)               const;
                 { return do_tolower(c); }
    const char* tolower(char* low, const char* high) const
                 { return do_tolower(low, high); }
    char  widen(char c) const { return c; }
    const char* widen(const char* lo, const char* hi, char* to) const
             { memcpy(to, lo, hi-lo); return hi; }
    char   narrow(char c, char /*dfault*/) const { return c; }
    const char* narrow(const char* lo, const char* hi,
                       char /*dfault*/, char* to) const
             { memcpy(to, lo, hi-lo); return hi; }
    static locale::id id;

    ctype(const ctype* tab = 0, bool del = false, size_t refs = 0)
      : ctype_base(id, refs), table_(tab ? tab : classic_table_),
        delete_it_(tab ? del : false) {}
  protected:
    ~ctype() { if (delete_it) delete table_; }
  };
  locale::id locale::ctype<char>::id;

  22.2.2.2  Template class ctype_byname        [lib.locale.ctype.byname]
  template <class charT>
  class locale::ctype_byname : public locale::ctype<charT> {
    // this class is specialized by vendors for char and wchar_t.
   protected:
    // ... declarations for all virtuals.
   public:
    ctype_byname(const char*, size_t refs = 0);
   protected:
    ~ctype_byname();
  };

  22.2.2.3  Convenience interfaces        [lib.locale.ctype.convenience]
  template <class charT> inline bool locale::isspace(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::SPACE, c); }
  template <class charT> inline bool locale::isprint(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::PRINT, c); }
  template <class charT> inline bool locale::iscntrl(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::CNTRL, c); }
  template <class charT> inline bool locale::isupper(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::UPPER, c); }
  template <class charT> inline bool locale::islower(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::LOWER, c); }
  template <class charT> inline bool locale::isalpha(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::ALPHA, c); }
  template <class charT> inline bool locale::isdigit(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::DIGIT, c); }
  template <class charT> inline bool locale::ispunct(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::PUNCT, c); }
  template <class charT> inline bool locale::isxdigit(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::XDIGIT, c); }
  template <class charT> inline bool locale::isalnum(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::ALNUM, c); }
  template <class charT> inline bool locale::isgraph(charT c) const
    { return use<locale::ctype<charT> >().is(locale::ctype<charT>::GRAPH, c); }

  template <class charT> inline charT locale::toupper(charT c) const
    { return use<locale::ctype<charT> >().toupper(c); }
  template <class charT> inline charT locale::tolower(charT c) const
    { return use<locale::ctype<charT> >().tolower(c); }

  22.2.3  The numeric facet                          [lib.facet.numeric]

  22.2.3.1  Template class num_get                  [lib.locale.num.get]
  template <class charT, class InputIterator = istreambuf_iterator<charT> >
  class locale::num_get : public locale::facet {
  public:
    typedef charT       char_type;
    typedef InputIterator iter_type;
    typedef basic_ios<charT> ios;

    // members of locale::num_get take a locale argument because they
    //   may need to refer to the locale's numpunct facet.

  protected:
    virtual iter_type do_get(iter_type, ios&, const locale&,
                             bool& v)          const;
    virtual iter_type do_get(iter_type, ios&, const locale&,
                             long& v)          const;
    virtual iter_type do_get(iter_type, ios&, const locale&,
                             unsigned long& v) const;
  //  virtual iter_type do_get(iter_type, ios&, const locale&,
  //                           long long& v)   const;
    virtual iter_type do_get(iter_type, ios&, const locale&,
                             double& v)        const;
    virtual iter_type do_get(iter_type, ios&, const locale&,
                             long double& v)   const;
  public:
    iter_type get(iter_type s, ios& f, const locale&, bool& v)          const;
      { return this->do_get(s, f, l, v); }
    iter_type get(iter_type s, ios& f, const locale&, long& v)          const;
      { return this->do_get(s, f, l, v); }
    iter_type get(iter_type s, ios& f, const locale&, unsigned long& v) const;
      { return this->do_get(s, f, l, v); }
  //  iter_type get(iter_type s, ios& f, const locale&, long long& v)   const;
  //    { return this->do_get(s, f, l, v); }
    iter_type get(iter_type s, ios& f, const locale&, double& v)        const;
      { return this->do_get(s, f, l, v); }
    iter_type get(iter_type s, ios& f, const locale&, long double& v)   const;
      { return this->do_get(s, f, l, v); }

    static locale::id id;

    num_get(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~num_get() {}
  };
  template <class charT, class InputIterator = istreambuf_iterator<charT> >
  locale::id locale::num_get<charT, InputIterator>::id;

1 The  classes locale::num_get<> and num_put<> handle numeric formatting
  and parsing.  Virtual  functions  are  provided  for  several  numeric
  types;  implementations  are allowed to delegate conversion of smaller
  types to extractors for larger ones, but are  not  required  to.   The
  functions  take a locale argument because their base class implementa­
  tion refers to locale::numpunct  features,  which  identify  preferred
  numeric  punctuation.   Extractors  and  inserters  for  the  standard
  iostreams are required to  call  locale::num_get  and  num_put  member
  functions.   The  ios& argument is used both for format control and to
  report errors.

  22.2.3.2  Template class num_put                  [lib.locale.num.put]
  template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
  class locale::num_put : public locale::facet {
    typedef charT       char_type;
    typedef OutputIterator iter_type;
    typedef basic_ios<charT> ios;

    // Members of locale::num_put take a locale argument because they
    //   may need to refer to the locale's numpunct facet.  The ios&
    //   argument is used for formatting reference only and error reporting.

  protected:
    virtual iter_type do_put(iter_type, ios&, const locale&, bool v)      const;
    virtual iter_type do_put(iter_type, ios&, const locale&, long v)      const;
    virtual iter_type do_put(iter_type, ios&, const locale&, unsigned long)
      const;
  //virtual iter_type do_put(iter_type, ios&, const locale&, long long v) const;
    virtual iter_type do_put(iter_type, ios&, const locale&, double v)    const;
    virtual iter_type do_put(iter_type, ios&, const locale&, long double v)
      const;
  public:
    iter_type put(iter_type s, ios& f, const locale& l, bool v)          const
      { return this->do_put(s, f, l, v); }
    iter_type put(iter_type s, ios& f, const locale& l, long v)          const
      { return this->do_put(s, f, l, v); }
    iter_type put(iter_type s, ios& f, const locale& l, unsigned long v) const
      { return this->do_put(s, f, l, v); }
  //  iter_type put(iter_type s, ios& f, const locale& l, long long v)   const
  //    { return this->do_put(s, f, l, v); }
    iter_type put(iter_type s, ios& f, const locale& l, double v)        const
      { return this->do_put(s, f, l, v); }
    iter_type put(iter_type s, ios& f, const locale& l, long double v)   const
      { return this->do_put(s, f, l, v); }

    static locale::id id;

    num_put(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~num_put() {}
  };
  template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
  locale::id locale::num_put<charT, OutputIterator>::id;

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

  22.2.4.1  Template class numpunct                [lib.locale.numpunct]
  // locale::numpunct is used by locale::num_get and num_put facets.

  template <class charT>
  class locale::numpunct : public locale::facet {
  public:
    typedef charT char_type;
    typedef basic_string<charT> string;
  protected:
    virtual string do_decimal_point() const;
    virtual string do_thousands_sep() const;
    virtual vector<char>  do_grouping() const;
    virtual string  do_truename() const;  // for bool
    virtual string  do_falsename() const; // for bool

  public:
    string decimal_point()   const { return do_decimal_point(); }
    string thousands_sep()   const { return do_thousands_sep(); }
    vector<char>  grouping() const { return do_grouping(); }
    string truename()        const { return do_truename(); }
    string falsename()       const { return do_falsename(); }

    static locale::id id;

    numpunct(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~numpunct() {}
  };
  template <class charT> locale::id locale::numpunct<charT>::id;

1 numpunct<> specifies numeric punctuation.   The  base  class  provides
  classic  "C"  numeric formats, while the _byname version supports gen­
  eral POSIX numeric formatting semantics.

  22.2.4.2  Template class                  [lib.locale.numpunct.byname]
       numpunct_byname
  template <class charT>
  class locale::numpunct_byname : public locale::numpunct<charT> {
    // this class is specialized by vendors for char and wchar_t.
  protected:
    // ... declarations for all virtuals.
  public:
    numpunct_byname(const char*, size_t refs = 0);
  protected:
    ~numpunct_byname();
  };

  22.2.5  The collation facet                        [lib.facet.collate]

  22.2.5.1  Template class collate                  [lib.locale.collate]
  // locale.use<locale::collate>() is used for string comparisons.

  template <class charT>
  class locale::collate : public locale::facet {
  public:
    typedef charT               char_type;
    typedef basic_string<charT> string;
  protected:
    virtual int    do_collate(const char* low1, const char* high1,
                              const char* low2, const char* high2);;
    virtual string do_transform(const char* low, const char* high);
    virtual long   do_hash(     const char* low, const char* high);

  public:
    int collate(const char* low1, const char* high1,
                const char* low2, const char* high2);;
    string transform(const char* low, const char* high);
    long hash(const char* low, const char* high);

    static locale::id id;

    collate(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~collate() {}
  };
  template <class charT> locale::id locale::collate<charT>::id;

1 The class locale::collate<charT> provides features for use in the col­
  lation  of  strings.   A  locale member function template, operator(),
  uses the collate facet to allow a locale to act directly as the predi­
  cate  argument  for  algorithms.   The  base  class uses lexicographic
  ordering.

  22.2.5.2  Template class                   [lib.locale.collate.byname]
       collate_byname
  template <class charT>
  class locale::collate_byname : public locale::collate<charT> {
    // this class is specialized by vendors for char and wchar_t.
  protected:
    // ... declarations for all virtuals.
  public:
    collate_byname(const char*);
  protected:
    ~collate_byname();
  };
  //  this template function satisfies requirements for a
  //  comparator predicate template argument:

  template <class charT>
  inline bool locale::operator()(const basic_string<charT>& s1,
                                 const basic_string<charT>& s2);
  {
     return use< collate<charT> >().collate(s1.begin(), s1.end(),
                                            s2.begin(), s2.end()) < 0;
  }

  22.2.6  The codeset conversion facet               [lib.facet.codecvt]

  22.2.6.1  Template class codecvt                  [lib.locale.codecvt]

  template <class fromT, class toT, class stateT>
  class locale::codecvt : public locale::facet {
    // use two of these to convert both ways
  public:
    typedef fromT  from_type;
    typedef toT    to_type;
    typedef stateT state_type;

    enum result { ok = 0, partial, error }
  protected:
    virtual result do_convert(stateT& state,
      const fromT* from, const fromT* from_end, const fromT*& from_next,
            toT*   to,   toT*         to_limit,       toT*&   to_next);
  public:
     result convert(stateT& state,
       const fromT* from, const fromT* from_end, const fromT*& from_next,
               toT*   to,         toT* to_limit,         toT*& to_next);

    static locale::id id;

    codecvt(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~codecvt() {}
  };
  template <class fromT, class toT, class stateT>
  locale::id locale::codecvt<fromT, toT, stateT>::id;

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

2 Its  only  member  function,  convert(),  returns an enumeration value
  which indicates whether it completed the conversion (ok), ran  out  of
  space  in the destination (partial), or encountered a "from" character
  it could not convert (error).

3 In all cases it leaves the from_next and to_next pointers pointing one
  beyond the last character successfully converted.

4 The stateT argument selects the pair of codesets being mapped between.
  Base class members are pure virtual.

5 Implementations are obliged  to  provide  specializations  for  <char,
  wchar_t, mbstate_t> and <wchar_t, char, mbstate_t>.

  22.2.6.2  Template class                   [lib.locale.codecvt.byname]
       codecvt_byname

  template <class fromT, class toT, class stateT>
  class locale::codecvt_byname : public locale::codecvt<fromT, toT, stateT> {
   protected:
    // ... declarations for all virtuals.
   public:
    codecvt_byname(const char*, size_t refs = 0);
   protected:
    ~codecvt_byname();
  };

  22.2.7  The date and time facet                  [lib.facet.date.time]

1 The  classes  locale::time_get<charT> and time_put<charT> provide date
  and time formatting and parsing.  The time formatting  function  put()
  takes  an  extra  format  argument to accommodate the POSIX strftime()
  extensions.  The ios& argument is  used  for  format  control  and  to
  report errors.

  22.2.7.1  Template class time_get                [lib.locale.time.get]
  template <class charT, class InputIterator = istreambuf_iterator<charT> >
  class locale::time_get : public locale::facet {
  public:
    typedef charT       char_type;
    typedef InputIterator iter_type;
    typedef basic_ios<charT> ios;

    enum dateorder { NO_ORDER, DMY, MDY, YMD, YDM };
  protected:
    virtual dateorder do_date_order()  const;

    virtual iter_type do_get_time(iter_type s, ios&, const locale&, tm* t) const;
    virtual iter_type do_get_date(iter_type s, ios&, const locale&, tm* t) const;
    virtual iter_type do_get_weekday(iter_type s, ios&, const locale&, tm* t)
                      const;
    virtual iter_type do_get_monthname(iter_type s, ios&, const locale&, tm* t)
                      const;
    virtual iter_type do_get_year(iter_type s, ios&, const locale&, tm* t) const;

  public:
    dateorder date_order()  const { return do_date_order(); }
    iter_type get_time(iter_type s, ios& f, const locale& l, tm* t)  const
      { return do_get_time(s,f,l,t); }
    iter_type get_date(iter_type s, ios& f, const locale& l, tm* t)  const
      { return do_get_date(s,f,l,t); }
    iter_type get_weekday(iter_type s, ios& f, const locale& l, tm* t) const
      { return do_get_weekday(s,f,l,t); }
    iter_type get_monthname(iter_type s, ios& f, const locale& l, tm* t) const
      { return do_get_monthname(s,f,l,t); }
    iter_type get_year(iter_type s, ios& f, const locale& l, tm* t) const
      { return do_get_year(s,f,l,t); }

    static locale::id id;

    time_get(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~time_get() {}
  };
  template <class charT, class InputIterator = istreambuf_iterator<charT> >
  locale::id locale::time<charT, InputIterator>::id;

  22.2.7.2  Template class                  [lib.locale.time.get.byname]
       time_get_byname
  template <class charT, class InputIterator = istreambuf_iterator<charT> >
  class locale::time_get_byname : public locale::time_get<charT, InputIterator> {
  protected:
    // ... declarations for all virtuals.
  public:
    time_get_byname(const char*, size_t refs = 0);
  protected:
    ~time_get_byname();
  };

  22.2.7.3  Template class time_put                [lib.locale.time.put]
  template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
  class locale::time_put : public locale::facet {
  public:
    typedef charT       char_type;
    typedef OutputIterator iter_type;
    typedef basic_ios<charT> ios;
  protected:
    virtual iter_type do_put(iter_type s, ios&, const locale&, const tm* t,
                        char format, char modifier) const;

  public:
    // the following is implemented in terms of other member functions.
    iter_type put(iter_type s, ios& f, struct tm const* tmb,
             const charT* pattern, const charT* pat_end) const;

    iter_type put(iter_type s, ios& f, const locale& l, struct tm const* t,
             char format, char modifier = ' ') const
      { return do_put(s,f,l,tmb,format,modifier); }

    static locale::id id;

    time_put(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~time_put() {}
  };
  template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
  locale::id locale::time_put<charT, OutputIterator>::id;

  22.2.7.4  Template class                  [lib.locale.time.put.byname]
       time_put_byname
  template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
  class locale::time_put_byname : public locale::time_put<charT, OutputIterator>
  {
  protected:
    // ... declarations for all virtuals.
  public:
    time_put_byname(const char*, size_t refs = 0);
  protected:
    ~time_put_byname();
  };

  22.2.8  The money facet                              [lib.facet.money]

1 These  handle  money  formats.  A template parameter indicates whether
  local or international monetary formats are to be  used.   money_get<>
  and  money_put<>  use  locale::moneypunct<>  features  if appropriate.
  locale::moneypunct<> provides basic format information for money  pro­
  cessing.   The  ios& argument is used for format control and to report
  errors.

  22.2.8.1  Template class money_get              [lib.locale.money.get]
  template <class charT, bool Intl = false,
            class InputIterator = istreambuf_iterator<charT> >
  class locale::money_get : public locale::facet {
    typedef charT       char_type;
    const bool          intl = Intl;
    typedef InputIterator iter_type;
    typedef basic_string<charT> string;
    typedef basic_ios<charT> ios;
  protected:
    virtual iter_type do_get(iter_type, ios&, const locale&, double& units) const;
    virtual iter_type do_get(iter_type, ios&, const locale&, string& digits) const;

  public:
    iter_type get(iter_type s, ios& f, const locale& l, double& units) const
       { return do_get(s, f, l, units); }
    iter_type get(iter_type s, ios& f, const locale& l, string& digits) const
       { return do_get(s, f, l, digits); }

    static locale::id id;

    money_get(size_t refs = 0) : locale::facet(refs) {}
   protected:
    ~money_get() {}
  };

  template <class charT, bool Intl = false,
            class InputIterator = istreambuf_iterator<charT> >
  locale::id locale::money_get<charT, Intl, InputIterator>::id;

  22.2.8.2  Template class money_put              [lib.locale.money.put]
  template <class charT, bool Intl = false,
            class OutputIterator = ostreambuf_iterator<charT> >
  class locale::money_put : public locale::facet {
  public:
    typedef charT       char_type;
    const bool          intl = Intl;
    typedef OutputIterator iter_type;
    typedef basic_string<charT> string;
    typedef basic_ios<charT> ios;
  protected
    virtual iter_type do_put(iter_type, ios&, const locale&, double units) const;
    virtual iter_type do_put(iter_type, ios&, const locale&, const string& digits) const;
  public:
    iter_type put(iter_type s, ios& f, const locale& l, double units) const
       { return do_put(s, f, l, units); }
    iter_type put(iter_type s, ios& f, const locale& l, const string& dgts) const
       { return do_put(s, f, l, dgts); }

    static locale::id id;

    money_put(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~money_put() {}
  };

  template <class charT, bool Intl = false,
            class OutputIterator = ostreambuf_iterator<charT> >
  locale::id locale::money_put<charT, Intl, OutputIterator>::id;

  22.2.9  The money punctuation facet             [lib.facet.moneypunct]

  22.2.9.1  Template class moneypunct            [lib.locale.moneypunct]

  template <class charT, bool International = false>
  class locale::moneypunct : public locale::facet {
  public:
    typedef charT char_type;
    const bool intl = International;
    typedef basic_string<charT> string;

    enum part { SYMBOL='$', SIGN='-', SPACE=' ', VALUE='v', NONE=' ' };
    struct pattern { char field[4]; };
  protected:
    virtual charT        do_decimal_point()  const;
    virtual charT        do_thousands_sep()  const;
    virtual vector<char> do_grouping()       const;
    virtual string       do_curr_symbol()    const;
    virtual string       do_positive_sign()  const;
    virtual string       do_negative_sign()  const;
    virtual int          do_frac_digits()    const;
    virtual pattern      do_format()         const;
  public:
    charT        decimal_point() const  { return do_decimal_point(); }
    charT        thousands_sep() const  { return do_thousands_sep(); }
    vector<char> grouping()      const  { return do_grouping(); }
    string       curr_symbol()   const  { return do_curr_symbol(); };
    string       positive_sign() const  { return do_positive_sign; }
    string       negative_sign() const  { return do_negative_sign; }
    int          frac_digits()   const  { return do_frac_digits(); }
    pattern      format()        const  { return do_format(); }

    static locale::id id;

    moneypunct(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~moneypunct() {}
  };

  template <class charT, bool Intl = false>
  locale::id locale::moneypunct<charT, Intl>::id;

1 This provides money punctuation, similar to numpunct above.

  22.2.9.2  Template class                [lib.locale.moneypunct.byname]
       moneypunct_byname
  template <class charT, bool Intl = false>
  class locale::moneypunct_byname : public locale::moneypunct<charT, Intl> {
   protected:
    // ... declarations for all virtuals.
   public:
    moneypunct_byname(const char*, size_t refs = 0);
   protected:
    ~moneypunct_byname();
  };

  22.2.10  The message retrieval facet              [lib.facet.messages]

1 Class  locale::msg<charT>  implements  POSIX  message  retrieval.   It
  should  be flexible enough to retrieve messages from X, MS Windows, or
  Macintosh resource files as well.

  22.2.10.1  Template class msg                         [lib.locale.msg]
  template <class charT>
  class locale::msg {
  public:
    typedef charT char_type;
    typedef int   catalog;
    typedef basic_string<charT> string;
  protected:
    virtual catalog do_open(const string&, const locale&) const;
    virtual string  do_get(catalog, int set, int msgid,
                           const string& default)         const;
    virtual void    do_close(catalog) const;
  public:
    catalog open(const string& fn, const locale& l) const
      { return do_open(fn, l); }
    string get(catalog c, int set, int msgid, const string& default) const
      { return do_get(c, set, msgid, default); }
    void close(catalog c) const { do_close(c); }
    static locale::id id;

    msg(size_t refs = 0) : locale::facet(refs) {}
  protected:
    ~msg() {}
  };

  template <class charT> locale::id locale::msg<charT>::id;

  22.2.10.2  Template class msg_byname           [lib.locale.msg.byname]
  template <class charT>
  class locale::msg_byname : public locale::msg<charT> {
  protected:
    // ... declarations for all virtuals.
  public:
    msg_byname(const char*, size_t refs = 0);
  protected:
    ~msg_byname();
  };

  22.2.11  User-defined facets                     [lib.facets.examples]

1 A user-defined facet may be added to a locale and used identically  as
  the  built-in  facets.   To  create a new facet interface users simply
  derive, from locale::facet, a class containing a static member: static
  locale::id id;.  (The locale member function templates verify its type
  and storage class.)

2 For   those   curious   about   the   mechanics:   this    initializa­
  tion/identification  system depends only on the initialization 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  excep­
  tion to be thrown.

3 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;
    }

4 In other words, C library localization is unaffected.

5 Traditional global localization is still easy:
    #include <iostream>
    #include <locale>

    int main(int argc, char** argv)
    {
      using namespace std;
      locale::global(locale(""));  // set the global locale
       cin.imbue(locale());        // imbue it on the std streams
      cout.imbue(locale());
      cerr.imbue(locale());
      return MyObject(argc, argv).doit();
    }

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

7 In  a  European  locale, with input 3.456,78, output is 3456.78.  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 preference.

8 Here is an example:
    // file: Date.h
    #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);
    ...

9 This example illustrates two architectural uses of class locale.   The
  first  is as a default argument in Date::asString(), where the default
  is the global (presumably user-preferred) locale.  The  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>
    #include <stringstream>

    std::string Date::asString(const std::locale& l)
    {
      using namespace std;
      stringstream s; s.imbue(l);
      s << *this; return s.data();
    }
    std::istream& operator>>(std::istream& s, Date& d)
    {
      using namespace std;
      if (!s.ipfx(0)) return s;
      locale loc = s.rdloc();
      struct tm t;
      loc.use<locale::time_get<char> >().get_date(s, s, loc, &t);
      if (s) d = Date(t.tm_day, t.tm_mon + 1, t.tm_year + 1900);
      s.isfx();
      return s;
    }

10A 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 you must define is the static member id, which  identifies
  your  class interface as a new facet.  For example, imagine we want to
  classify Japanese characters:

    // file: jctype.h
    #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 locale::ctype<wchar_t> ctype;

      locale loc(locale(""),       // the user's preferred locale ...
                 new My::JCType);  // and a new feature...

      wchar_t c = loc.use<ctype>().widen('!');
      if (loc.use<My::JCType>().is_kanji(c))
        cout << "no it isn't!" << endl;
      return 0;
    }

11The new facet is used exactly like the built-in facets.

12Replacing  an  existing facet is even easier.  Here we do not define a
  member id because we are  reusing  the  locale::numpunct<charT>  facet
  interface:

    // my_bool.C
    #include <iostream>
    #include <locale>
    #include <string>

    namespace My {
      using namespace std;
      typedef locale::numpunct_byname<char> numpunct;

      class BoolNames : public numpunct {
        typedef basic_string<char> string;
       protected:
        string do_truename()  { return "Oui Oui!"; }
        string do_falsename() { return "Mais Non!"; }
        ~BoolNames() {}
       public:
        BoolNames(const char* name) : numpunct(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 << "Any arguments today? " << (argc > 1) << endl;
      return 0;
    }

  22.3  C Library Locales                                [lib.c.locales]

1 Headers:

  --<clocale>

2 Table 2:

                    Table 2--Header <clocale> synopsis

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

  SEE ALSO: ISO C subclause 7.10.4.