______________________________________________________________________
22 Localization library [lib.localization]
______________________________________________________________________
1 This clause describes components that C++ programs may use to encapsu
late (and therefore be more portable when confronting) cultural dif
ferences. The locale facility includes internationalization support
for character classification and string collation, numeric, monetary,
and date/time formatting and parsing, and message retrieval.
2 The following subclauses describe components for locales themselves,
the standard facets, and facilities from the ISO C library, as summa
rized in Table 1:
Table 1--Localization library summary
+---------------------------------------------------------------+
| Subclause Header(s) |
+---------------------------------------------------------------+
|_lib.locales_ Locales <locale> |
|_lib.locale.categories_ Standard locale Categories |
+---------------------------------------------------------------+
|_lib.c.locales_ C library locales <clocale> |
+---------------------------------------------------------------+
22.1 Locales [lib.locales]
Header <locale> synopsis
#include <limits>
#include <string>
#include <iosfwd>
#include <stdexcept> // for runtime_error
#include <vector> // for vector<char>
namespace std {
// subclause _lib.locale_, locale:
class locale;
template <class Facet> const Facet& use_facet(const locale&);
template <class Facet> bool has_facet(const locale&) throw();
template <class charT, class Traits>
basic_ostream<charT,Traits>&
operator<<(basic_ostream<charT,Traits>& s, const locale& loc);
template <class charT, class Traits>
basic_istream<charT,Traits>&
operator>>(basic_istream<charT,Traits>& s, locale& loc);
// subclause _lib.locale.convenience_, convenience interfaces:
template <class charT> bool isspace (charT c, const locale& loc) const;
template <class charT> bool isprint (charT c, const locale& loc) const;
template <class charT> bool iscntrl (charT c, const locale& loc) const;
template <class charT> bool isupper (charT c, const locale& loc) const;
template <class charT> bool islower (charT c, const locale& loc) const;
template <class charT> bool isalpha (charT c, const locale& loc) const;
template <class charT> bool isdigit (charT c, const locale& loc) const;
template <class charT> bool ispunct (charT c, const locale& loc) const;
template <class charT> bool isxdigit(charT c, const locale& loc) const;
template <class charT> bool isalnum (charT c, const locale& loc) const;
template <class charT> bool isgraph (charT c, const locale& loc) const;
template <class charT> charT toupper(charT c, const locale& loc) const;
template <class charT> charT tolower(charT c, const locale& loc) const;
// subclauses _lib.category.ctype_ and _lib.facet.ctype.special_, ctype:
class ctype_base;
template <class charT> class ctype;
class ctype<char>; // specialization
template <class charT> class ctype_byname;
class ctype_byname<char>; // specialization
class codecvt_base;
template <class fromT, class toT, class stateT> class codecvt;
template <class fromT, class toT, class stateT> class codecvt_byname;
// subclauses _lib.category.numeric_ and _lib.facet.numpunct_, numeric:
template <class charT, class InputIterator> class num_get;
template <class charT, class OutputIterator> class num_put;
template <class charT> class numpunct;
template <class charT> class numpunct_byname;
// subclause _lib.category.collate_, collation:
template <class charT> class collate;
template <class charT> class collate_byname;
// subclause _lib.category.time_, date and time:
class time_base;
template <class charT, class InputIterator> class time_get;
template <class charT, class InputIterator> class time_get_byname;
template <class charT, class OutputIterator> class time_put;
template <class charT, class OutputIterator> class time_put_byname;
// subclauses _lib.category.monetary_, money:
class money_base;
template <class charT, class InputIterator> class money_get;
template <class charT, class OutputIterator> class money_put;
template <class charT> class moneypunct;
template <class charT> 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)
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, category);
locale(const locale& other, const locale& one, category);
~locale() throw(); // non-virtual
const locale& operator=(const locale& other) throw;
// locale operations:
basic_string<char> name() const;
bool operator==(const locale& other) const;
bool operator!=(const locale& other) const;
template <class charT,Traits>
bool operator()(const basic_string<charT,Traits>& s1,
const basic_string<charT,Traits>& s2) const;
_________________________
1) In this subclause, the type name struct tm is an incomplete type
that is defined in <ctime>.
// global locale objects:
static locale global(const locale&);
static const locale& classic();
static locale transparent();
};
}
+------- BEGIN BOX 1 -------+
Change: Added a third argument, category, to the second constructor
template above for consistency with the definition in
[lib.locale.cons]
+------- END BOX 1 -------+
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 (and special
ized, for simplicity of exposition) as:2)
ostream& operator<<(ostream& s, double f)
{
if (s.opfx()) {
locale loc = s.getloc();
use_facet< num_put<char> >(loc).put(s, s, loc, f);
}
s.osfx();
return s;
}
--end example]
+------- BEGIN BOX 2 -------+
Error handling must be added to the example above, once it is decided
what to do.
+------- END BOX 2 -------+
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_).
_________________________
2) Notice that, in the call to put, the stream is implicitly converted
to an ostreambuf_iterator.
5 [Note: All locale semantics are accessed via use_facet<> and
has_facet<>, except that:
--A member operator template operator()(basic_string<C,T>&,
basic_string<C,T>&) is provided so that a locale may be used as a
predicate argument to the standard collections, to collate strings.
--Convenient global interfaces are provided for traditional ctype
functions such as isdigit() and isspace(), so that given a locale
object loc a C++ program can call isspace(c,loc). (This eases
upgrading existing extractors (_lib.istream.formatted_).) --end
note]
6 A locale which does not implement a facet delegates to the global
locale in effect at the time that instantiation of use_facet<> is
first called on that facet (_lib.locale.statics_).
7 An instance of locale is immutable; once a facet reference is obtained
from it, that reference remains usable as long as the locale value
itself exists. The effect of imbuing on a stream (_lib.ios.base_,
_lib.ios_), or installing as the global locale, the result of static
member locale::transparent() (or any locale with similar behavior) is
unspecified.
8 Caching results from calls to locale facet member functions during
calls to iostream inserters and extractors, and in streambufs between
calls to basic_streambuf::imbue, is explicitly supported
(_lib.streambuf_).3)
9 A locale constructed from a name string (such as "POSIX"), or from
parts of two named locales, or read from a stream, has a name; all
others do not. Named locales may be compared for equality; an unnamed
locale is equal only to (copies of) itself. For an unnamed locale,
locale::name() returns the string *".
22.1.1.1 locale types [lib.locale.types]
22.1.1.1.1 Type locale::category [lib.locale.category]
typedef unsigned category;
1 Valid category values include 0 and the locale member bitmask elements
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.
_________________________
3) This implies that member functions of iostream classes cannot safe
ly call imbue() themselves, except as specified elsewhere.
+------- BEGIN BOX 3 -------+
Change: The proposal (N0699,22-003), specified that "&" meant "union",
and "|" intersection. This was seen as a typo.
+------- END BOX 3 -------+
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,wchar_t,mbstate_t>, |
| codecvt<wchar_t,char,mbstate_t> |
+------------------------------------------------------------+
|monetary moneypunct<char>, moneypunct<wchar_t> |
| moneypunct<char,true>, moneypunct<wchar_t,true>, |
| money_get<char>, money_get<wchar_t> |
| money_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> |
+------------------------------------------------------------+
+------- BEGIN BOX 4 -------+
Editorial Proposal: Add money_get<char,true>, money_get<wchar_t,true>,
money_put<char,true>, and money_put<wchar_t,true>, or eliminate the
bool template parameter and add a parameter to the get() and put()
members to choose at runtime which moneypunct<> facet to use.
+------- END BOX 4 -------+
3 For any locale loc either constructed, or returned by
locale::classic(), and any facet Facet that is a member of a standard
category, has_facet<Facet>(loc) is true. Each locale member function
which takes a locale::category argument operates on the corresponding
set of facets.
4 An implementation is required to provide those instantiations for
facet templates identified as members of a category, and for those
shown in Table 3:
Table 3--Required Instantiations
+---------------------------------------------------------------+
|Category Includes Facets |
+---------------------------------------------------------------+
|collate collate_byname<char>, collate_byname<wchar_t> |
+---------------------------------------------------------------+
|ctype ctype_byname<char>, ctype_byname<wchar_t> |
+---------------------------------------------------------------+
|monetary moneypunct_byname<char,International>, |
| moneypunct_byname<wchar_t,International>, |
| money_get<char,International,InputIterator>, |
| money_get<wchar_t,International,InputIterator>, |
| money_put<char,International,OutputIterator>, |
| money_put<wchar_t,International,OutputIterator> |
+---------------------------------------------------------------+
|numeric numpunct_byname<char>, numpunct_byname<wchar_t> |
| num_get<C,InputIterator>, num_put<C,OutputIterator> |
+---------------------------------------------------------------+
|time time_get<char,InputIterator>, |
| time_get_byname<char,InputIterator>, |
| time_get<wchar_t,OutputIterator>, |
| time_get_byname<wchar_t,OutputIterator>, |
| time_put<char,OutputIterator>, |
| time_put_byname<char,OutputIterator>, |
| time_put<wchar_t,OutputIterator> |
| time_put_byname<wchar_t,OutputIterator> |
+---------------------------------------------------------------+
+------- BEGIN BOX 5 -------+
Change: In the money_get<> and money_put<> facets of the table above,
a template argument International has been added to be consistent with
the definition of those facets.
+------- END BOX 5 -------+
5 For the facets num_get<> and num_put<> the implementation provided
must depend only on the corresponding facets numpunct<> and ctype<>,
instantiated on the same character type. Other facets are allowed to
depend on any other facet that is part of a standard category.
6 In declarations of facets, a template formal parameter with name
InputIterator or OutputIterator indicates the set of all possible
instantiations on parameters that satisfy the requirements of an Input
Iterator or an Output Iterator, respectively
(_lib.iterator.requirements_). A template formal parameter with name
C represents the set of all possible instantiations on a parameter
that satisfies the requirements for a character on which any of the
iostream components can be instantiated.
+------- BEGIN BOX 6 -------+
Editorial Proposal Those facets represented with a template parameter
International represent the set of all possible instantiations on both
true and false. [Alternatively, remove the bool parameter from those
templates, and add a bool argument to their get() and put() members
instead.]
+------- END BOX 6 -------+
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
reference 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 Identification of a locale facet interface, 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 locale instance whose value is a snapshot of the cur
rent global locale state as set by locale::global(locale&) or the C
function setlocale(). This constructor is commonly used as the
default value for arguments of functions that take a locale argu
ment.
locale(const locale& other) throw();
Effects:
Constructs a locale which is a copy of other.
const locale& operator=(const locale& other) throw();
Effects:
Creates a copy of other, replacing the current value.
Returns:
*this
explicit locale(const char* std_name);
Effects:
Constructs a locale using standard C locale names, e.g. "POSIX".
The resulting locale implements semantics defined to be associated
with that name. Throws runtime_error if the argument is not valid.
Notes:
The set of valid string argument values is "C", "", and any imple
mentation-defined values.
locale(const locale& other, const char* std_name, category);
Effects:
Constructs a locale as a copy of other except for the facets identi
fied by the category argument, which instead implement the same
semantics as locale(std_name).
Notes:
The locale has a name if and only if other has a name.
template <class Facet> locale(const locale& other, Facet* f);
Effects:
Constructs a locale incorporating all facets from the first argument
except that of type Facet, and installs the second argument as the
remaining facet.
Notes:
The resulting locale has no name.
+------- BEGIN BOX 7 -------+
Editorial proposal: What if the pointer parameter is 0? Recommend:
Throw runtime_error.
+------- END BOX 7 -------+
template <class Facet> locale(const locale& other, const locale& one);
Effects:
Constructs a locale incorporating all facets from the first argument
except that identified by Facet, and that facet from the second
argument instead.
Throws:
runtime_error if has_facet<Facet>(one) is false.
Notes:
The resulting locale has no name.
locale(const locale& other, const locale& one, category cats);
Effects:
Constructs a locale incorporating all facets from the first argument
except those that implement cats, which are instead incorporated
from the second argument.
Notes:
The resulting locale has a name if and only if the first two argu
ments have names.
~locale() throw();
2 A non-virtual destructor that throws no exceptions.
22.1.1.3 locale members [lib.locale.members]
basic_string<char> name() const;
Returns:
The name of *this, if it has one; otherwise, the string "*".
22.1.1.4 locale operators [lib.locale.operators]
bool operator==(const locale& other) const;
Returns:
true if both arguments are the same locale, or one is a copy of the
other, or each has a name and the names are identical; false other
wise.
bool operator!=(const locale& other) const;
Returns:
The result of the expression: !(*this == other)
template <class charT, class Traits>
bool operator()(const basic_string<charT,Traits>& s1,
const basic_string<charT,Traits>& s2) const;
Effects:
Compares two strings according to the collate<charT> facet.
Notes:
This member operator template (and therefore locale itself) satis
fies requirements for a comparator predicate template argument
(_lib.algorithms_) applied to strings.
Returns:
The result of the following expression:
use_facet< collate<charT> >(*this).compare(s1.data(), s1.data()+s1.size(),
s2.data(), s2.data()+s2.size()) < 0;
1 [Example: A vector of strings v can be collated according to collation
rules in locale loc simply by (_lib.alg.sort_, _lib.vector_):
std::sort(v.begin(), v.end(), loc);
--end example]
22.1.1.5 locale static members [lib.locale.statics]
static locale global(const locale& loc);
1 Replaces ::setlocale().
Effects:
Sets the global locale to its argument. Subsequent calls to the
default constructor, and of other library functions affected by the
function setlocale(), use the locale loc until the next call to this
member or setlocale().
Returns:
The previous global locale.
static const locale& classic();
2 The "C" locale.
Returns:
A locale that implements the classic "C" locale semantics, equiva
lent to the value locale("C").
Notes:
This locale, its facets, and their member functions, do not change
with time.
static locale transparent();
3 The continuously updated global locale.
Returns:
A locale which implements semantics that vary dynamically as the
global locale is changed.
Notes:
The effect of imbuing this locale into an iostreams component is
unspecified (_lib.ios.members_).
22.1.2 locale globals [lib.locale.global.templates]
template <class Facet> const Facet& use_facet(const locale& loc);
1 Get a reference to a facet of a locale.
Effects:
If the requested Facet is not present in loc, but is present in the
current global locale, returns the global locale's instance of
Facet. Because locale objects are immutable, subsequent calls to
use_facet<Facet>(loc) return the same object, regardless of subse
quent calls to setlocale or locale::global.
Notes:
The only exception to this rule is for the locale returned by
locale::transparent(); it always returns the facet found in the
global locale at the time of each call.
Throws:
bad_cast if (has_facet<Facet>(*this) || has_facet<Facet>(locale()))
is false, or other unspecified objects catchable as exception.
Returns:
A reference to the requested facet.
Notes:
The result is guaranteed by locale's value semantics to last as long
as the value of locP.
+------- BEGIN BOX 8 -------+
Is bad_cast the best choice of exceptions to throw?
+------- END BOX 8 -------+
template <class Facet> bool has_facet(const locale& loc) throw();
Returns:
An indication whether the facet requested is present in loc. If
use_facet<Facet>(loc) has already been called successfully, returns
true.
Notes:
has_facet<Facet>(locale::transparent()) always returns false.
template <class charT, class Traits>
basic_ostream<charT,Traits>&
operator<<(basic_ostream<charT,Traits>& s, const locale& loc);
2 The regular stream output operator for locales
(_lib.ostream.formatted_).
Effects:
s << loc.name() << endl.
Returns:
The output stream argument s.
template <class charT, class Traits>
basic_istream<charT,Traits>&
operator>>(basic_istream<charT,Traits>& s, loc& loc);
3 The regular stream input operator for locales
(_lib.istream.formatted_).
Effects:
Read a line into a string and construct a locale from it. If either
operation fails, indicates a failure by calling
s.setstate(ios_base::failbit) (which may throw ios_base::failure
(_lib.iostate.flags_), otherwise, assigns the constructed locale
object into the argument loc.
Returns:
s.
22.1.3 Convenience interfaces [lib.locale.convenience]
22.1.3.1 Character classification [lib.classification]
template <class charT> bool isspace (charT c, const locale& loc) const;
template <class charT> bool isprint (charT c, const locale& loc) const;
template <class charT> bool iscntrl (charT c, const locale& loc) const;
template <class charT> bool isupper (charT c, const locale& loc) const;
template <class charT> bool islower (charT c, const locale& loc) const;
template <class charT> bool isalpha (charT c, const locale& loc) const;
template <class charT> bool isdigit (charT c, const locale& loc) const;
template <class charT> bool ispunct (charT c, const locale& loc) const;
template <class charT> bool isxdigit(charT c, const locale& loc) const;
template <class charT> bool isalnum (charT c, const locale& loc) const;
template <class charT> bool isgraph (charT c, const locale& loc) const;
1 Each of these functions isF returns the result of the expression:
use_facet< ctype<charT> >(loc).is(ctype_base::F, c)
where F is the ctype_base::mask value corresponding to that function
(_lib.category.ctype_).4)
22.1.3.2 Character conversions [lib.conversions]
template <class charT> charT toupper(charT c, const locale& loc) const;
Returns:
use_facet<ctype<charT> >(loc).toupper(c).
template <class charT> charT tolower(charT c, const locale& loc) const;
Returns:
loc.template use<ctype<charT> >().tolower(c).
_________________________
4) When used loop, it is faster to cache the ctype<> facet and use it
directly, or use the vector form of ctype<>::is.
22.2 Standard locale categories [lib.locale.categories]
1 Each of the standard categories includes a family of facets. Some of
these implement formatting or parsing, intended for use by standard or
users' operators << and >>. Those that take a basic_ios<charT>& argu
ment obey all formatting conventions specified for members of that
class, including width() and fill() (_lib.ios.base_).
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 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;
};
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 first
form returns the result of the expression (M & m) != 0. The second
form simply places M for all *p where (low<=p && p<high), into
vec[p-low].
Returns:
The first form returns true if the character has the characteristics
specified. The second form returns high.
const char* 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 char* 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.
Effects:
The second form replaces each character *p in the range [low, high)
for which a corresponding upper-case character exists, with that
character.
Returns:
The first form returns the corresponding upper-case character if it
is known to exist, or its argument if not. The second form returns
high.
charT do_tolower(charT c) const;
const charT* do_tolower(charT* low, const charT* high) const;
Effects:
Converts a character or characters to upper case.
Effects:
The second form replaces each character *p in the range [low, high)
and for which a corresponding lower-case character exists, with that
character.
Returns:
The first form returns the corresponding lower-case character if it
is known to exist, or its argument if not. The second form returns
high.
charT do_widen(char c) const;
const char* do_widen(const char* low, const char* high,
charT* dest) const;
Effects:
Applies the simplest reasonable transformation from a char value or
sequence of char values to the corresponding charT value or values.
The only characters for which unique transformations are required
are the digits, alphabetic characters, '-', '+', newline, and space.
For any named ctype category with a ctype<charT> facet ctw and valid
ctype_base::mask value M, however, (is(M, c) || !ctw.is(M,
do_widen(c)) ) is true.5)
The second form transforms each character *p in the range [low,
high), placing the result in dest[p-low].
Returns:
The first form returns the transformed value. The second form
returns high
char do_narrow(charT c, char dfault) const;
const charT* do_narrow(const charT* low, const charT* high,
char dfault, char* dest) const;
Effects:
Applies the simplest reasonable transformation from a charT value or
sequence of charT values to the corresponding char value or values.
The only characters for which unique transformations are required
are the digits, alphabetic characters, '-', '+', newline, and space.
For any named ctype category with a ctype<char> facet ctc however,
and ctype_base::mask value M,
(is(M,c) || !ctc.is(M, do_narrow(c),dfault) )"
is true (unless do_narrow returns dfault). In addition, for any
digit character c, the expression (do_narrow(c,dfault)-'0') evalu
ates to the digit value of the character. The second form trans
forms each character *p in the range [low, high), placing the result
(or dfault if no simple transformation is readly available) in
dest[p-low].
Returns:
The first form returns the transformed value; or dfault if no map
ping is readily available. The second form returns high.
22.2.1.2 Template class ctype_byname [lib.locale.ctype.byname]
_________________________
5) In other words, the transformed character is not a member of any
character classification that c is not also a member of.
template <class charT>
class ctype_byname : public ctype<charT> {
public:
explicit ctype_byname(const char*, size_t refs = 0);
protected:
~ctype_byname(); // virtual
virtual bool do_is(mask m, charT c) const;
virtual const charT* do_is(const charT* low, const charT* high,
mask* vec) const;
virtual const char* do_scan_is(mask m,
const charT* low, const charT* high) const;
virtual const char* do_scan_not(mask m,
const charT* low, const charT* high) const;
virtual charT do_toupper(charT) const;
virtual const charT* do_toupper(charT* low, const charT* high) const;
virtual charT do_tolower(charT) const;
virtual const charT* do_tolower(charT* low, const charT* high) const;
virtual charT do_widen(char) const;
virtual const char* do_widen(const char* low, const char* high,
charT* dest) const;
virtual char do_narrow(charT, char dfault) const;
virtual const charT* do_narrow(const charT* low, const charT* high,
char dfault, char* dest) const;
};
}
+------- BEGIN BOX 9 -------+
Change: In the previous Draft, the above class definition mistakenly
described the specialization ctype_byname<char>. That definition has
been moved to its proper section, and this one fleshed out according
to the original proposal.
+------- END BOX 9 -------+
22.2.1.3 ctype specializations [lib.facet.ctype.special]
namespace std {
class ctype<char> : public locale::facet, public ctype_base {
public:
typedef char char_type;
explicit ctype(const mask* tab = 0, bool del = false,
size_t refs = 0);
bool is(mask m, char c) const;
const char* is(const char* low, const char* high, mask* vec) const;
const char* scan_is (mask m,
const char* low, const char* high) const;
const char* scan_not(mask m,
const char* low, const char* high) const;
char toupper(char c) const;
const char* toupper(char* low, const char* high) const;
char tolower(char c) const;
const char* tolower(char* low, const char* high) const;
char widen(char c) const;
const char* widen(const char* low, const char* high, char* to) const;
char narrow(char c, char dfault) const;
const char* narrow(const char* low, const char* high, char dfault,
char* to) const;
static locale::id id;
protected:
const mask* table() const;
static const mask* classic_table();
~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)
+------- BEGIN BOX 10 -------+
Editorial Proposal: Members table() and classic_table() should be
marked throw().
+------- END BOX 10 -------+
22.2.1.3.1 ctype<char> destructor [lib.facet.ctype.char.dtor]
~ctype();
Effects:
If the constructor's first argument was nonzero, and its second
argument was true, does delete [] table().
22.2.1.3.2 ctype<char> members [lib.facet.ctype.char.members]
explicit ctype(const mask* tab = 0, bool del = false,
size_t refs = 0);
Effects:
Passes its refs argument to its base class constructor.
_________________________
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>.
bool is(mask m, char c) const;
const char* is(const char* low, const char* high,
mask* vec) const;
Effects:
The second form, for all *p in the range [low, high), assigns vec[p-
low] to table()[(unsigned char)*p].
Returns:
The first form returns table()[(unsigned char)c] & m; the second
form returns high.
const char* scan_is(mask m,
const char* low, const char* high) const;
Returns:
The smallest p in the range [low, high) such that
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;
Returns:
The first constructor argument, if it was non-zero, otherwise clas
sic_table().
+------- BEGIN BOX 11 -------+
Editorial proposal: table() should be marked throw().
+------- END BOX 11 -------+
22.2.1.3.3 ctype<char> static [lib.facet.ctype.char.statics]
members
static const mask* classic_table();
Returns:
A pointer the initial element of an array of size
numeric_limits<unsigned char>::max() + 1 which represents the clas
sifications of characters in the "C" locale.
+------- BEGIN BOX 12 -------+
Editorial proposal: classic_table() should be marked throw().
+------- END BOX 12 -------+
22.2.1.3.4 ctype<char> virtual [lib.facet.ctype.char.virtuals]
functions
char do_toupper(char) const;
const char* do_toupper(char* low, const char* high) const;
char do_tolower(char) const;
const char* do_tolower(char* low, const char* high) const;
These functions are described identically as those members of the same
name in the ctype class template (_lib.locale.ctype.members_).
22.2.1.4 Class [lib.locale.ctype.byname.special]
ctype_byname<char>
class ctype_byname<char> : public ctype<charT> {
public:
explicit ctype_byname(const char*, size_t refs = 0);
protected:
~ctype_byname(); // virtual
virtual char do_toupper(char) const;
virtual const char* do_toupper(char* low, const char* high) const;
virtual char do_tolower(char) const;
virtual const char* do_tolower(char* low, const char* high) const;
};
}
1
22.2.1.5 Template class codecvt [lib.locale.codecvt]
namespace std {
class codecvt_base {
public:
enum result { ok, partial, error, noconv };
};
template <class fromT, class toT, class stateT>
class codecvt : public locale::facet, public codecvt_base {
public:
typedef fromT from_type;
typedef toT to_type;
typedef stateT state_type;
explicit codecvt(size_t refs = 0)
result convert(stateT& state,
const fromT* from, const fromT* from_end, const fromT*& from_next,
toT* to, toT* to_limit, toT*& to_next) const;
static locale::id id;
protected:
~codecvt(); // virtual
virtual result do_convert(stateT& state,
const fromT* from, const fromT* from_end, const fromT*& from_next,
toT* to, toT* to_limit, toT*& to_next) const;
};
}
1 The class codecvt<fromT,toT,stateT> is for use when converting from
one codeset to another, such as from wide characters to multibyte
characters, or between wide character sets such as Unicode and EUC.
Instances of this facet are typically used in pairs instantiated oppo
sitely.
2 The stateT argument selects the pair of codesets being mapped between.
3 Implementations are required to provide instantiations for
<char,wchar_t,mbstate_t> and <wchar_t,char,mbstate_t>. Instantiations
on mbstate_t perform conversion between encodings known to the library
implementor. Other encodings can be converted by specializing on a
user-defined stateT type. The stateT object can contain any state
that is useful to communicate to or from the specialized do_convert
member. The base class implementations convert the implementation-
defined native execution codeset.
22.2.1.5.1 codecvt members [lib.locale.codecvt.members]
result convert(stateT& state,
const fromT* from, const fromT* from_end, const fromT*& from_next,
toT* to, toT* to_limit, toT*& to_next) const;
Returns:
do_convert(state, from,from_end,from_next, to,to_limit,to_next);
22.2.1.5.2 codecvt virtual [lib.locale.codecvt.virtuals]
functions
result do_convert(stateT& state,
const fromT* from, const fromT* from_end, const fromT*& from_next,
toT* to, toT* to_limit, toT*& to_next) const;
Preconditions:
(from<=from_end && to<=to_end) well-defined and true; state initial
ized, if at the beginning of a sequence, or else equal to the result
of converting the preceding characters in the sequence.
Effects:
Translates characters in the range [from,from_end), placing the
results in sequential positions starting at *to. Converts no more
than (from_end-from) fromT elements, and stores no more than
(to_limit-to) toT elements.
Stops if it encounters a character it cannot convert. It always
leaves the from_next and to_next pointers pointing one beyond the
last character successfully converted.
If no translation is needed (returns noconv), sets to_next equal to
argument to.
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 ran out of space in the destination |
|error encountered a from_type character it could not convert |
|noconv no conversion was needed |
+-----------------------------------------------------------------+
22.2.1.6 Template class [lib.locale.codecvt.byname]
codecvt_byname
namespace std {
template <class fromT, class toT, class stateT>
class codecvt_byname : public codecvt<fromT, toT, stateT> {
public:
explicit codecvt_byname(const char*, size_t refs = 0);
protected:
~codecvt_byname(); // virtual
virtual result do_convert(stateT& state,
const fromT* from, const fromT* from_end, const fromT*& from_next,
toT* to, toT* to_limit, toT*& to_next) const;
};
}
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 are allowed to delegate extraction of smaller types to
extractors for larger types, but are not required to do so.
2 The functions take a locale argument because their base class imple
mentation relies on numpunct<> members to identify all numeric punctu
ation preferences, and on ctype<> members to perform character classi
fication.
3 Extractor and inserter members of the standard iostreams are required
to use num_get<> and num_put<> member functions for formatting and
parsing (_lib.istream.formatted.reqmts_,
_lib.ostream.formatted.reqmts_). The ios_type& argument is used both
for format control, and to report errors, as described in subclauses
_lib.iostate.flags_ and _lib.fmtflags.state_.
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;
typedef basic_ios<charT> ios_type;
explicit num_get(size_t refs = 0);
iter_type get(iter_type in, iter_type end, ios_type&,
const locale&, bool& v) const;
iter_type get(iter_type in, iter_type end, ios_type& ,
const locale&, long& v) const;
iter_type get(iter_type in, iter_type end, ios_type&,
const locale&, unsigned long& v) const;
iter_type get(iter_type in, iter_type end, ios_type&,
const locale&, double& v) const;
iter_type get(iter_type in, iter_type end, ios_type&,
const locale&, long double& v) const;
static locale::id id;
protected:
~num_get(); // virtual
virtual iter_type do_get(iter_type, iter_type, ios_type&, const locale&,
bool& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_type&, const locale&,
long& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_type&, const locale&,
unsigned long& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_type&, const locale&,
double& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_type&, const locale&,
long double& v) const;
};
}
1 The facet num_get is used to parse numeric values from an input
sequence such as an istream.
22.2.2.1.1 num_get members [lib.facet.num.get.members]
iter_type get(iter_type in, iter_type end, ios_type& str
const locale& loc, bool& val) const;
iter_type get(iter_type in, iter_type end, ios_type& str
const locale& loc, long& val) const;
iter_type get(iter_type in, iter_type end, ios_type& str
const locale& loc, unsigned long& val) const;
iter_type get(iter_type in, iter_type end, ios_type& str
const locale& loc, double& val) const;
iter_type get(iter_type in, iter_type end, ios_type& str
const locale& loc, long double& val) const;
Returns:
do_get(in, end, str, loc, 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_type& str
const locale& loc, bool& val) const;
iter_type do_get(iter_type in, iter_type end, ios_type& str
const locale& loc, long& val) const;
iter_type do_get(iter_type in, iter_type end, ios_type& str
const locale& loc, unsigned long& val) const;
iter_type do_get(iter_type in, iter_type end, ios_type& str
const locale& loc, double& val) const;
iter_type do_get(iter_type in, iter_type end, ios_type& str
const locale& loc, long double& val) const;
Effects:
Reads characters from in, interpreting them according to
str.flags(), loc.use template< ctype<charT> >, and loc.use template<
numpunct<charT> >. do_get() ignores the value of str.rdstate();
however, indicates failure by calling str.setstate(failbit) (which
may throw ios_base::failure (_lib.iostate.flags_)).
If an error occurs, val is unchanged; otherwise it is set to the
resulting value.
Notes:
Digit group separators are optional; if present, digit grouping is
checked after the entire number is read. When reading a non-numeric
boolean value, the names are compared exactly.
Returns:
An iterator pointing one past the last character consumed as part of
the converted field.
22.2.2.2 Template class num_put [lib.locale.num.put]
namespace std {
template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
class num_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
typedef basic_ios<charT> ios_type;
explicit num_put(size_t refs = 0);
iter_type put(iter_type s, ios_type& f, const locale& loc, bool v) const;
iter_type put(iter_type s, ios_type& f, const locale& loc, long v) const;
iter_type put(iter_type s, ios_type& f, const locale& loc,
unsigned long v) const;
iter_type put(iter_type s, ios_type& f, const locale& loc, double v) const;
iter_type put(iter_type s, ios_type& f, const locale& loc,
long double v) const;
static locale::id id;
protected:
~num_put(); // virtual
virtual iter_type do_put(iter_type, ios_type&, const locale&, bool v) const;
virtual iter_type do_put(iter_type, ios_type&, const locale&, long v) const;
virtual iter_type do_put(iter_type, ios_type&, const locale&,
unsigned long) const;
virtual iter_type do_put(iter_type, ios_type&, const locale&, double v) const;
virtual iter_type do_put(iter_type, ios_type&, const locale&,
long double v) const;
};
}
1 The facet num_put is used to format numeric values to a character
sequence such as an ostream.
22.2.2.2.1 num_put members [lib.facet.num.put.members]
iter_type put(iter_type out, ios_type& str
const locale& loc, bool val) const;
iter_type put(iter_type out, ios_type& str
const locale& loc, long val) const;
iter_type put(iter_type out, ios_type& str
const locale& loc, unsigned long val) const;
iter_type put(iter_type out, ios_type& str
const locale& loc, double val) const;
iter_type put(iter_type out, ios_type& str
const locale& loc, long double val) const;
Returns:
do_put(out, str, loc, val).
22.2.2.2.2 num_put virtual [lib.facet.num.put.virtuals]
functions
iter_type do_put(iter_type out, ios_type& str
const locale& loc, bool val) const;
iter_type do_put(iter_type out, ios_type& str
const locale& loc, long val) const;
iter_type do_put(iter_type out, ios_type& str
const locale& loc, unsigned long val) const;
iter_type do_put(iter_type out, ios_type& str
const locale& loc, double val) const;
iter_type do_put(iter_type out, ios_type& str
const locale& loc, long double val) const;
Effects:
Writes characters to the sequence out, formatting val according to
str.flags(), loc.use template< ctype<charT> >, and loc.use template<
numpunct<charT> >. Inserts digit group separators as specified by
numpunct<charT>::do_grouping.
Notes:
do_put() ignores and does not change the result of str.rdstate()
(_lib.ios.base_).
Returns:
An iterator pointing immediately after the last character produced.
+------- BEGIN BOX 13 -------+
What if do_put cannot produce all the characters requested? Is there
a way to bound how much storage do_put will consume? If we don't know
if the puts fail, how can ostream member functions set badbit as they
are required to do? The same questions apply to the put functions
later in this clause.
+------- END BOX 13 -------+
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);
string_type decimal_point() const;
string_type thousands_sep() const;
vector<char> grouping() const;
string_type truename() const;
string_type falsename() const;
static locale::id id;
protected:
~numpunct(); // virtual
virtual string_type do_decimal_point() const;
virtual string_type do_thousands_sep() const;
virtual vector<char> do_grouping() const;
virtual string_type do_truename() const; // for bool
virtual string_type do_falsename() const; // for bool
};
}
1 numpunct<> specifies numeric punctuation. The base class provides
classic C" numeric formats, while the _byname" version supports named
locale (e.g. POSIX, X/Open) numeric formatting semantics.
2 The syntax for number formats is as follows, where digit represents
the radix set specified by the fmtflags argument value, whitespace is
as determined by the facet ctype<charT> (_lib.locale.ctype_), and
thousands-sep and decimal-point are the results of corresponding
numpunct<charT> members. Integer values have the format:
integer ::= [sign] units
sign ::= plusminus [whitespace]
plusminus ::= '+' | '-'
units ::= digits [thousands-sep units]
digits ::= digit [digits]
and floating-point values have:
floatval ::= [sign] units [decimal-point [digits]] [e [sign] digits] |
[sign] decimal-point digits [e [sign] digits]
e ::= 'e' | 'E'
where the number of digits between thousands-seps is as specified by
do_grouping(). For parsing, if the digits portion contains no thou
sands-separators, no grouping constraint is applied.
+------- BEGIN BOX 14 -------+
Is support for syntax like "0xFF" required for iostreams support? If
so, we need to add language describing it.
+------- END BOX 14 -------+
22.2.3.1.1 numpunct members [lib.facet.numpunct.members]
string_type decimal_point() const;
Returns:
do_decimal_point()
string_type thousands_sep() const;
Returns:
thousands_sep()
vector<char> 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
string_type do_decimal_point() const;
Returns:
A basic_string<charT> for use as the decimal radix separator. If
this is not a one-character string, num_get<charT,InputIterator> is
not required to recognize numbers formatted using it.
The base class implementation returns ".".
string_type do_thousands_sep() const;
Returns:
A basic_string<charT> for use as the digit group separator. If this
is longer than one character, num_get<charT,InputIterator> is not
required to recognize numbers formatted with it.
The base class implementation returns the empty string.
vector<char> do_grouping() const;
Returns:
A vector vec in which each element vec[i] represents the number of
digits in the group at position i starting with 0 as the rightmost
group. If vec.size() <= i, the number is the same as group (i-1);
if (i<0 || vec[i]<=0), the size of the digit group is unlimited.
The base class implementation returns the empty vector.
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 string_type do_decimal_point() const;
virtual string_type do_thousands_sep() const;
virtual vector<char> do_grouping() const;
virtual string_type do_truename() const; // for bool
virtual string_type do_falsename() const; // for bool
};
}
22.2.4 The collate category [lib.category.collate]
22.2.4.1 Template class collate [lib.locale.collate]
namespace std {
template <class charT>
class collate : public locale::facet {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit collate(size_t refs = 0);
int compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
string_type transform(const charT* low, const charT* high) const;
long hash(const charT* low, const charT* high) const;
static locale::id id;
protected:
~collate(); // virtual
virtual int do_compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
virtual string_type do_transform(const charT* low, const charT* high) const;
virtual long do_hash (const charT* low, const charT* high) const;
};
}
1 The class collate<charT> provides features for use in the collation
(comparison) and hashing of strings. A locale member function tem
plate, operator(), uses the collate facet to allow a locale to act
directly as the predicate argument for standard algorithms
(_lib.algorithms_) and containers operating on strings. The base
class implementation applies lexicographic ordering
(_lib.alg.lex.comparison_).
2 Each function compares a string of characters *p in the range
[low,high).
22.2.4.1.1 collate members [lib.locale.collate.members]
int compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
Returns:
do_compare(low1, high1, low2, high2)
string_type transform(const charT* low, const charT* high) const;
Returns:
do_transform(low, high)
long hash(const charT* low, const charT* high) const;
Returns:
do_hash(low, high)
22.2.4.1.2 collate virtual [lib.locale.collate.virtuals]
functions
int do_compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
Returns:
1 if the first string is greater than the second, -1 if less, zero
otherwise. The base class implementation implements a lexicographi
cal comparison (_lib.alg.lex.comparison_).
string_type do_transform(const charT* low, const charT* high) const;
Returns:
A basic_string<charT> value that, compared lexicographically with
the result of calling transform() on another string, yields the same
result as calling do_compare() on the same two strings.7)
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<unsignedlong>::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;
};
_________________________
7) This function is useful when one string is being compared to many
other strings.
22.2.5 The time category [lib.category.time]
1 The classes time_get<charT,InputIterator> and
time_put<charT,OutputIterator> provide date and time formatting and
parsing. The ios_type& argument is used both for format control, and
to report errors, as described in subclauses _lib.ios::fmtflags_ and
_lib.ios::iostate_.
22.2.5.1 Template class time_get [lib.locale.time.get]
namespace std {
class time_base {
public:
enum dateorder { no_order, dmy, mdy, ymd, ydm };
};
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class time_get : public locale::facet, public time_base {
public:
typedef charT char_type;
typedef InputIterator iter_type;
typedef basic_ios<charT> ios_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_type& f,
const locale& loc, tm* t) const;
iter_type get_date(iter_type s, iter_type end, ios_type& f,
const locale& loc, tm* t) const;
iter_type get_weekday(iter_type s, iter_type end, ios_type& f,
const locale& loc, tm* t) const;
iter_type get_monthname(iter_type s, iter_type end, ios_type& f,
const locale& loc, tm* t) const;
iter_type get_year(iter_type s, iter_type end, ios_type& f,
const locale& loc, 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_type&,
const locale&, tm* t) const;
virtual iter_type do_get_date(iter_type s, iter_type end, ios_type&,
const locale&, tm* t) const;
virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_type&,
const locale&, tm* t) const;
virtual iter_type do_get_monthname(iter_type s, ios_type&,
const locale&, tm* t) const;
virtual iter_type do_get_year(iter_type s, iter_type end, ios_type&,
const locale&, 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.8)
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_type& str,
const locale& loc, tm* t) const;
Returns:
do_get_time(s, end, str, loc, t)
iter_type get_date(iter_type s, iter_type end, ios_type& str,
const locale& loc, tm* t) const;
Returns:
do_get_date(s, end, str, loc, t)
iter_type get_weekday(iter_type s, iter_type end, ios_type& str,
const locale&loc, tm* t) const;
iter_type get_monthname(iter_type s, iter_type end, ios_type& str,
const locale& loc, tm* t) const;
Returns:
do_get_weekday(s, end, str, loc, t) or do_get_monthname(s, end, str,
loc, t
iter_type get_year(iter_type s, iter_type end, ios_type& str,
const locale& loc, tm* t) const;
Returns:
do_get_year(s, end, str, loc, t)
_________________________
8) 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.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 dates composed of day, month, and year.
Returns no_order if the date format specified by 'X' contains other
variable components (e.g Julian day, week number, week day).
iter_type do_get_time(iter_type s, iter_type end, ios_type& str,
const locale&, 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.
Indicates an error by calling, str.setstate(failbit), which may
throw ios_base::failure (_lib.iostate.flags_)).
Returns:
An iterator pointing immediately beyond the last character recog
nized as part of the time, if no error occurred.
iter_type do_get_date(iter_type s, iter_type end, ios_type& str,
const locale&, 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.
Indicates failure by calling str.setstate(failbit) (which may throw
ios_base::failure (_lib.iostate.flags_)).
Returns:
An iterator pointing immediately beyond the last character recog
nized as part of the date, if no error occurred.
iter_type do_get_weekday(iter_type s, iter_type end, ios_type& str,
const locale&, tm* t) const;
iter_type do_get_monthname(iter_type s, iter_type end, ios_type& str,
const locale&, 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.
Indicates failure by calling str.setstate(failbit) (which may throw
ios_base::failure (_lib.iostate.flags_)).
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_type& str,
const locale&, tm* t) const;
Effects:
Reads characters starting at s until it has extracted an unambiguous
year identifier. It is unspecified whether two-digit year numbers
are accepted, or what century they are assumed to lie in. Sets the
t->tm_year member accordingly.
Indicates failure by calling str.setstate(failbit) (which may throw
ios_base::failure (_lib.iostate.flags_)).
Returns:
An iterator pointing immediately beyond the last character recog
nized as part of a valid year identifier.
+------- BEGIN BOX 15 -------+
Editorial proposal: Should this say "implementation-defined" rather
than "unspecified"?
+------- END BOX 15 -------+
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_type&,
const locale&, tm* t) const;
virtual iter_type do_get_date(iter_type s, iter_type end, ios_type&,
const locale&, tm* t) const;
virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_type&,
const locale&, tm* t) const;
virtual iter_type do_get_monthname(iter_type s, iter_type end, ios_type&,
const locale&, tm* t) const;
virtual iter_type do_get_year(iter_type s, iter_type end, ios_type&,
const locale&, 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;
typedef basic_ios<charT> ios_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_type& f, const locale& loc, const tm* tmb,
const charT* pattern, const charT* pat_end) const;
iter_type put(iter_type s, ios_type& f, const locale& loc,
const tm* t, char format, char modifier = 0) const;
static locale::id id;
protected:
~time_put(); // virtual
virtual iter_type do_put(iter_type s, ios_type&, const locale&, 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_type&, const locale&, const tm* t,
const charT* pattern, const charT* pat_end) const;
iter_type put(iter_type s, ios_type&, const locale&, 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_type&, const locale&, 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
specifiers in the string argument to the standard library function
strftime().9)
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_type&, const locale&, const tm* t,
char format, char modifier) const;
};
}
22.2.6 The monetary category [lib.category.monetary]
1 These templates handle monetary formats. A template parameter indi
cates whether local or international monetary formats are to be used.
money_get<> and money_put<> use moneypunct<> members to determine all
formatting details. moneypunct<> provides basic format information
for money processing. The ios_type& argument is used both for format
control, and to report errors, as described in subclauses
_lib.ios::fmtflags_ and _lib.ios::iostate_.
22.2.6.1 Template class money_get [lib.locale.money.get]
namespace std {
template <class charT, bool Intl = false,
class InputIterator = istreambuf_iterator<charT> >
class money_get : public locale::facet {
public:
typedef charT char_type;
typedef InputIterator iter_type;
typedef basic_string<charT> string_type;
typedef basic_ios<charT> ios_type;
explicit money_get(size_t refs = 0);
iter_type get(iter_type s, iter_type end, ios_type& f,
const locale& loc, double& units) const;
iter_type get(iter_type s, iter_type end, ios_type& f,
const locale& loc, string_type& digits) const;
static const bool intl = Intl;
static locale::id id;
_________________________
9) Interpretation of the modifier argument is implementation-defined,
but should follow POSIX conventions.
protected:
~money_get(); // virtual
virtual iter_type do_get(iter_type, iter_type, ios_type&, const locale&,
double& units) const;
virtual iter_type do_get(iter_type, iter_type, ios_type&, const locale&,
string_type& digits) const;
};
}
22.2.6.1.1 money_get members [lib.locale.money.get.members]
iter_type get(iter_type s, iter_type end, ios_type& f,
const locale& loc, double& quant) const;
iter_type get(s, iter_type end, ios_type&f,
const locale& loc, string_type& quant) const;
Returns:
do_get(s, end, f, loc, quant)
22.2.6.1.2 money_get virtual [lib.locale.money.get.virtuals]
functions
iter_type do_get(iter_type s, iter_type end, ios_type& str,
const locale& loc, double& units) const;
iter_type do_get(iter_type s, iter_type end, ios_type& strfP,
const locale& loc, string_type& digits) const;
Effects:
Reads characters from s until it has constructed a monetary value,
as specified in str.flags() and the moneypunct<charT> facet of loc,
or until it encounters an error or runs out of characters. The
result is a pure sequence of digits, representing a count of the
smallest unit of currency representable.10) Digit group separators
are optional; if present, digit grouping is checked after all syn
tactic elements have been read. Where space or none appear in the
format pattern, except at the end, optional whitespace is consumed.
If (str.flags() & ios_type::showbase) is false, the currency symbol
is optional, and if it appears after all other required syntactic
elements it is not consumed. If the expression above is true, the
currency symbol is required, and is always consumed. If the first
character of the a sign appears in its correct position, any remain
ing sign characters are required, and consumed. [Example: If show
base is off, then when the sign is "()" and the currency symbol is
"L", in "(100 L)" the "L" is consumed; but in "-100 L" it is not.
--end example] Sets the argument units or digits from the sequence
of digits found. units is negated, or digits is preceded by '-',
for a negative value.
_________________________
10) For example, the sequence $1,056.23 in a common U.S. locale would
yield, for units, 105623, or for digits, 105623".
Indicates failure by calling str.setstate(failbit) (which may throw
ios_base::failure (_lib.iostate.flags_)).
On error, the units or digits argument is unchanged.
Returns:
An iterator pointing immediately beyond the last character recog
nized as part of a valid monetary quantity.
+------- BEGIN BOX 16 -------+
The description above needs further review.
+------- END BOX 16 -------+
22.2.6.2 Template class money_put [lib.locale.money.put]
namespace std {
template <class charT, bool Intl = false,
class OutputIterator = ostreambuf_iterator<charT> >
class money_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
typedef basic_string<charT> string_type;
typedef basic_ios<charT> ios_type;
explicit money_put(size_t refs = 0);
iter_type put(iter_type s, ios_type& f, const locale& loc,
double units) const;
iter_type put(iter_type s, ios_type& f, const locale& loc,
const string_type& digits) const;
static const bool intl = Intl;
static locale::id id;
protected:
~money_put(); // virtual
virtual iter_type
do_put(iter_type, ios_type&, const locale&, double units) const;
virtual iter_type
do_put(iter_type, ios_type&, const locale&,
const string_type& digits) const;
};
}
22.2.6.2.1 money_put members [lib.locale.money.put.members]
iter_type put(iter_type s, ios_type& f, const locale& loc,
double quant) const;
iter_type put(iter_type s, ios_type& f, const locale& loc,
const string_type& quant) const;
Returns:
do_put(s, f, loc, quant)
22.2.6.2.2 money_put virtual [lib.locale.money.put.virtuals]
functions
iter_type do_put(iter_type s, ios_type& str, const locale& loc,
double units) const;
iter_type do_put(iter_type s, ios_type& str, const locale& loc,
const string_type& digits) const;
Effects:
Writes characters to s, according to the format specified by the
moneypunct<charT> facet of loc, and str.flags(). Ignores any frac
tional part of units, or any characters in digits beyond the
(optional) leading '-' and immediately subsequent digits.
Notes:
The currency symbol is generated only if (str.flags() &
ios_type::showbase) is true. If ((str.flags() &
ios_type::adjustfield) == ios_type::internal) the fill characters
are placed where none or space appears in the formatting pattern
(_lib.money.get.virtuals_).
Returns:
An iterator pointing immediately after the last character produced.
22.2.6.3 Template class moneypunct [lib.locale.moneypunct]
namespace std {
class money_base {
public:
enum part { none, space, symbol, sign, value };
struct pattern { char field[4]; };
};
template <class charT, bool International = false>
class moneypunct : public locale::facet, public money_base {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit moneypunct(size_t refs = 0);
charT decimal_point() const;
charT thousands_sep() const;
vector<char> 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 vector<char> 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;
vector<char> 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.11)
_________________________
11) In common U.S. locales this is '.'.
charT do_thousands_sep() const;
Returns:
The digit group separator to use in case do_grouping() specifies a
digit grouping pattern.12)
vector<char> do_grouping() const;
Returns:
A pattern defined identically as the result of
numpunct<charT>::do_grouping().13)
string_type do_curr_symbol() const;
Returns:
A string to use as the currency identifier symbol.14)
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;15) 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.16)
pattern do_pos_format() const;
pattern do_neg_format() const;
Returns:
A pattern, a four-element array specifying the order in which
_________________________
12) In common U.S. locales this is ','.
13) This is most commonly the vector "{ 3 }"
14) For international instantiations (second template parameter true)
this is always four characters long, usually three letters and a
space.
15) This is usually the empty string.
16) In common U.S. locales, this is 2.
syntactic elements appear in the monetary format.
Notes:
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 ele
ments may appear in any order. In international instantiations, the
result is always { symbol, sign, none, value }.17)
22.2.6.4 Template class [lib.locale.moneypunct.byname]
moneypunct_byname
namespace std {
template <class charT, bool Intl = false>
class moneypunct_byname : public moneypunct<charT, Intl> {
public:
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 vector<char> 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 T1 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);
_________________________
17) Note that the international symbol usually contains a space, it
self; for example, "USD ".
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 The type of messages_base::catalog is implementation-defined. Valid
values of this type can be obtained only by default construction or by
calling member do_open. Default construction, copy construction, and
assignment operations on this type must be well-formed and not throw
exceptions, although the effect of copying invalid values is unde
fined.
22.2.7.1.1 messages members [lib.locale.messages.members]
catalog open(const basic_string<char>& name, const locale& loc) const;
Returns:
do_open(name, loc).
string_type get(catalog cat, int set, int msgid,
const string_type& dfault) const;
Returns:
do_get(cat, set, msgid, dfault).
void close(catalog cat) const;
Effects:
Calls do_close(cat).
22.2.7.1.2 messages virtual [lib.locale.messages.virtuals]
functions
catalog do_open(const basic_string<char>& name,
const locale& loc) const;
Returns:
A value that may be passed to get() to retrieve a message, from the
message catalog identified by the string name according to an imple
mentation-defined mapping. The result can be used until it is
passed to close().
Returns a value less than 0 if no such catalog can be opened.
Notes:
The locale argument loc is used for character set code conversion
when retrieving messages, if needed.
string_type do_get(catalog cat, int set, int msgid,
const string_type& dfault) const;
Requires:
A catalog cat obtained from open() and not yet closed.
Returns:
A message identified by arguments set, msgid, and dfault, according
to an implementation-defined mapping. If no such message can be
found, returns dfault.
void do_close(catalog cat) const;
Requires:
A catalog cat obtained from open() and not yet closed.
Effects:
Releases unspecified resources associated with cat.
Notes:
The limit on such resources, if any, is implementation-defined.
22.2.7.2 Template class [lib.locale.messages.byname]
messages_byname
namespace std {
template <class charT>
class messages_byname : public messages<charT> {
public:
explicit messages_byname(const char*, size_t refs = 0);
protected:
~messages_byname(); // virtual
virtual catalog do_open(const basic_string<char>&, const locale&) const;
virtual string_type do_get(catalog, int set, int msgid,
const string_type& dfault) const;
virtual void do_close(catalog) const;
};
}
22.2.8 Program-defined facets [lib.facets.examples]
1 A C++ program may define facets to be added to a locale and used iden
tically as the built-in facets. To create a new facet interface, C++
programs simply derive from locale::facet a class containing a static
member: static locale::id id.
2 [Note: The locale member function templates verify its type and stor
age class. --end note]
3 This initialization/identification system depends only on the initial
ization to 0 of static objects, before static constructors are called.
When an instance of a facet is installed in a locale, the locale
checks whether an id has been assigned, and if not, assigns one.
Before this occurs, any attempted use of its interface causes the
bad_cast exception to be thrown.
4 [Example: Here is a program that just calls C functions:
#include <locale>
extern "C" void c_function();
int main()
{
using namespace std;
locale::global(locale("")); // same as setlocale(LC_ALL, "");
c_function();
return 0;
}
In other words, C library localization is unaffected. --end example]
5 [Example: Traditional global localization is still easy:
#include <iostream>
#include <locale>
int main(int argc, char** argv)
{
using namespace std;
locale::global(locale("")); // set the global locale
cin.imbue(locale()); // imbue it on the std streams
cout.imbue(locale());
cerr.imbue(locale());
return MyObject(argc, argv).doit();
}
--end example]
6 [Example: Greater flexibility is possible:
#include <iostream>
#include <locale>
int main()
{
using namespace std;
cin.imbue(locale("")); // the user's preferred locale
cout.imbue(locale::classic());
double f;
while (cin >> f) cout << f << endl;
return (cin.fail() != 0);
}
In a European locale, with input 3.456,78, output is 3456.78. --end
example]
7 This can be important even for simple programs, which may need to
write a data file in a fixed format, regardless of a user's prefer
ence.
8 [Example: Here is an example of the use of locales in a library inter
face.
// file: Date.h
#include <iosfwd>
#include <string>
#include <locale>
...
class Date {
...
public:
Date(unsigned day, unsigned month, unsigned year);
std::string asString(const std::locale& = std::locale());
};
istream& operator>>(istream& s, Date& d);
ostream& operator<<(ostream& s, Date d);
...
This example illustrates two architectural uses of class locale.
9 The first is as a default argument in Date::asString(), where the
default is the global (presumably user-preferred) locale.
10The second is in the operators << and >>, where a locale "hitchhikes"
on another object, in this case a stream, to the point where it is
needed.
// file: Date.C
#include "Date" // includes <ctime>
#include <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.getloc();
struct tm t;
use_facet< time_get<char> >(loc).get_date(s, s, 0, loc, &t);
if (s) d = Date(t.tm_day, t.tm_mon + 1, t.tm_year + 1900);
s.isfx();
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 << "Any arguments today? " << (argc > 1) << endl;
return 0;
}
--end example]
22.3 C Library Locales [lib.c.locales]
1 Header <clocale> (Table 5):
Table 5--Header <clocale> synopsis
+-------------------------------------------------+
| Type Name(s) |
+-------------------------------------------------+
|Macros: |
| LC_ALL LC_COLLATE LC_CTYPE |
| LC_MONETARY LC_NUMERIC LC_TIME |
+-------------------------------------------------+
|Struct: lconv |
+-------------------------------------------------+
|Functions: localeconv setlocale |
+-------------------------------------------------+
2 The contents are the same as the Standard C library.
SEE ALSO: ISO C subclause 7.10.4.