______________________________________________________________________
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.
+------- BEGIN BOX 1 -------+
Change clause [lib.iterator.requirement] so that is explicitly says
that _all_ functions in the library, that take ranges, have to define
a reasonable behavior for valid ranges and may exhibit undefined
behavior for invalid ranges. So far, the standard states this only
for algorithms.
+------- END BOX 1 -------+
2 The following subclauses describe components for locales themselves,
the standard facets, and facilities from the ISO C library, as summa-
rized in Table 1:
Table 1--Localization library summary
+---------------------------------------------------------------+
| Subclause Header(s) |
+---------------------------------------------------------------+
|_lib.locales_ Locales <locale> |
|_lib.locale.categories_ Standard locale Categories |
+---------------------------------------------------------------+
|_lib.c.locales_ C library locales <clocale> |
+---------------------------------------------------------------+
22.1 Locales [lib.locales]
Header <locale> synopsis
namespace std {
// _lib.locale_, locale:
class locale;
template <class Facet> const Facet& use_facet(const locale&);
template <class Facet> bool has_facet(const locale&) throw();
// _lib.locale.convenience_, convenience interfaces:
template <class charT> bool isspace (charT c, const locale& loc);
template <class charT> bool isprint (charT c, const locale& loc);
template <class charT> bool iscntrl (charT c, const locale& loc);
template <class charT> bool isupper (charT c, const locale& loc);
template <class charT> bool islower (charT c, const locale& loc);
template <class charT> bool isalpha (charT c, const locale& loc);
template <class charT> bool isdigit (charT c, const locale& loc);
template <class charT> bool ispunct (charT c, const locale& loc);
template <class charT> bool isxdigit(charT c, const locale& loc);
template <class charT> bool isalnum (charT c, const locale& loc);
template <class charT> bool isgraph (charT c, const locale& loc);
template <class charT> charT toupper(charT c, const locale& loc);
template <class charT> charT tolower(charT c, const locale& loc);
// _lib.category.ctype_ and _lib.facet.ctype.special_, ctype:
class ctype_base;
template <class charT> class ctype;
template <> class ctype<char>; // specialization
template <class charT> class ctype_byname;
template <> class ctype_byname<char>; // specialization
class codecvt_base;
template <class internT, class externT, class stateT> class codecvt;
template <class internT, class externT, class stateT> class codecvt_byname;
// _lib.category.numeric_ and _lib.facet.numpunct_, numeric:
template <class charT, class InputIterator> class num_get;
template <class charT, class OutputIterator> class num_put;
template <class charT> class numpunct;
template <class charT> class numpunct_byname;
// _lib.category.collate_, collation:
template <class charT> class collate;
template <class charT> class collate_byname;
// _lib.category.time_, date and time:
class time_base;
template <class charT, class InputIterator> class time_get;
template <class charT, class InputIterator> class time_get_byname;
template <class charT, class OutputIterator> class time_put;
template <class charT, class OutputIterator> class time_put_byname;
// _lib.category.monetary_, money:
class money_base;
template <class charT, class InputIterator> class money_get;
template <class charT, class OutputIterator> class money_put;
template <class charT, bool Intl> class moneypunct;
template <class charT, bool Intl> class moneypunct_byname;
// _lib.category.messages_, message retrieval:
class messages_base;
template <class charT> class messages;
template <class charT> class messages_byname;
}
1 The header <locale> defines classes and declares functions that encap-
sulate and manipulate the information peculiar to a locale.1)
_________________________
1) In this subclause, the type name struct tm is an incomplete type
that is defined in <ctime>.
22.1.1 Class locale [lib.locale]
namespace std {
class locale {
public:
// types:
class facet;
class id;
typedef int category;
static const category // values assigned here are for exposition only
none = 0,
collate = 0x010, ctype = 0x020,
monetary = 0x040, numeric = 0x080,
time = 0x100, messages = 0x200,
all = collate | ctype | monetary | numeric | time | messages;
// construct/copy/destroy:
locale() throw()
locale(const locale& other) throw()
explicit locale(const char* std_name);
locale(const locale& other, const char* std_name, category);
template <class Facet> locale(const locale& other, Facet* f);
locale(const locale& other, const locale& one, category);
~locale() throw(); // non-virtual
const locale& operator=(const locale& other) throw();
template <class Facet> locale combine(const locale& other);
// locale operations:
basic_string<char> name() const;
bool operator==(const locale& other) const;
bool operator!=(const locale& other) const;
template <class charT, class Traits, class Allocator>
bool operator()(const basic_string<charT,Traits,Allocator>& s1,
const basic_string<charT,Traits,Allocator>& s2) const;
// global locale objects:
static locale global(const locale&);
static const locale& classic();
};
}
1 Class locale implements a type-safe polymorphic set of facets, indexed
by facet type. In other words, a facet has a dual role: in one sense,
it's just a class interface; at the same time, it's an index into a
locale's set of facets.
2 Access to the facets of a locale is via two function templates,
use_facet<> and has_facet<>.
3 [Example: An iostream operator<< might be implemented as:2)
_________________________
2) Notice that, in the call to put, the stream is implicitly converted
to an ostreambuf_iterator<charT,traits>.
template <class charT, class traits>
basic_ostream<charT,traits>&
operator<< (basic_ostream<charT,traits>& s, Date d)
{
typename basic_ostream<charT,traits>::sentry cerberos(s);
if (cerberos) {
ios_base::iostate err = 0;
tm tmbuf; d.extract(tmbuf);
use_facet< time_put<charT,ostreambuf_iterator<charT,traits> > >(
s.getloc()).put(s, s, s.fill(), err, &tmbuf, 'x');
s.setstate(err); // might throw
}
return s;
}
--end example]
4 In the call to use_facet<Facet>(loc), the type argument chooses a
facet, making available all members of the named type. If Facet is
not present in a locale (or, failing that, in the global locale), it
throws the standard exception bad_cast. A C++ program can check if a
locale implements a particular facet with the template function
has_facet<Facet>(). User-defined facets may be installed in a locale,
and used identically as may standard facets (_lib.facets.examples_).
5 [Note: All locale semantics are accessed via use_facet<> and
has_facet<>, except that:
--A member operator template operator()(basic_string<C,T,A>&,
basic_string<C,T,A>&) is provided so that a locale may be used as a
predicate argument to the standard collections, to collate strings.
--Convenient global interfaces are provided for traditional ctype
functions such as isdigit() and isspace(), so that given a locale
object loc a C++ program can call isspace(c,loc). (This eases
upgrading existing extractors (_lib.istream.formatted_).) --end
note]
6 An instance of locale is immutable; once a facet reference is obtained
from it, that reference remains usable as long as the locale value
itself exists.
7 In successive calls to a locale facet member function during a call to
an iostream inserter or extractor or a streambuf member function, the
returned result shall be identical. [Note: This implies that such
results may safely be reused without calling the locale facet member
function again, and that member functions of iostream classes cannot
safely call imbue() themselves, except as specified elsewhere. --end
note]
8 A locale constructed from a name string (such as "POSIX"), or from
parts of two named locales, has a name; all others do not. Named
locales may be compared for equality; an unnamed locale is equal only
to (copies of) itself. For an unnamed locale, locale::name() returns
the string *".
22.1.1.1 locale types [lib.locale.types]
22.1.1.1.1 Type locale::category [lib.locale.category]
typedef int category;
1 Valid category values include the locale member bitmask elements none,
collate, ctype, monetary, numeric, time, and messages. In addition,
locale member all is defined such that the expression
(collate | ctype | monetary | numeric | time | messages | all) == all
is true. Further, the result of applying operators | and & to any two
valid values is valid, and results in the setwise union and intersec-
tion, respectively, of the argument categories.
2 locale member functions expecting a category argument require either a
valid category value or one of the constants LC_CTYPE etc., defined in
<cctype>. Such a category value identifies a set of locale cate-
gories. Each locale category, in turn, identifies a set of locale
facets, including at least those shown in Table 2:
Table 2--Locale Category Facets
+------------------------------------------------------------+
|Category Includes Facets |
+------------------------------------------------------------+
|collate collate<char>, collate<wchar_t> |
+------------------------------------------------------------+
|ctype ctype<char>, ctype<wchar_t> |
| codecvt<char,char,mbstate_t>, |
| codecvt<wchar_t,char,mbstate_t> |
+------------------------------------------------------------+
|monetary moneypunct<char>, moneypunct<wchar_t> |
| moneypunct<char,true>, moneypunct<wchar_t,true>, |
| money_get<char>, money_get<wchar_t> |
| money_put<char>, money_put<wchar_t> |
+------------------------------------------------------------+
|numeric numpunct<char>, numpunct<wchar_t>, |
| num_get<char>, num_get<wchar_t> |
| num_put<char>, num_put<wchar_t> |
+------------------------------------------------------------+
|time time_get<char>, time_get<wchar_t>, |
| time_put<char>, time_put<wchar_t> |
+------------------------------------------------------------+
|messages messages<char>, messages<wchar_t> |
+------------------------------------------------------------+
3 For any locale loc either constructed, or returned by locale::clas-
sic(), and any facet Facet that is a member of a standard category,
has_facet<Facet>(loc) is true. Each locale member function which
takes a locale::category argument operates on the corresponding set of
facets.
4 An implementation is required to provide those instantiations for
facet templates identified as members of a category, and for those
shown in Table 3:
Table 3--Required Instantiations
+---------------------------------------------------------------+
|Category Includes Facets |
+---------------------------------------------------------------+
|collate collate_byname<char>, collate_byname<wchar_t> |
+---------------------------------------------------------------+
|ctype ctype_byname<char>, ctype_byname<wchar_t> |
+---------------------------------------------------------------+
|monetary moneypunct_byname<char,International>, |
| moneypunct_byname<wchar_t,International>, |
| money_get<C,InputIterator>, |
| money_put<C,OutputIterator> |
+---------------------------------------------------------------+
|numeric numpunct_byname<char>, numpunct_byname<wchar_t> |
| num_get<C,InputIterator>, num_put<C,OutputIterator> |
+---------------------------------------------------------------+
|time time_get<char,InputIterator>, |
| time_get_byname<char,InputIterator>, |
| time_get<wchar_t,OutputIterator>, |
| time_get_byname<wchar_t,OutputIterator>, |
| time_put<char,OutputIterator>, |
| time_put_byname<char,OutputIterator>, |
| time_put<wchar_t,OutputIterator> |
| time_put_byname<wchar_t,OutputIterator> |
+---------------------------------------------------------------+
|messages messages_byname<char>, messages_byname<wchar_t> |
+---------------------------------------------------------------+
5 The provided implementation of members of facets num_get<charT> and
num_put<charT> calls use_facet<F>(l) only for facet F of types
numpunct<charT> and ctype<charT>, and for locale l the value obtained
by calling member getloc() on the ios_base& argument to these func-
tions.
6 In declarations of facets, a template formal parameter with name
InputIterator or OutputIterator indicates the set of all possible
instantiations on parameters that satisfy the requirements of an Input
Iterator or an Output Iterator, respectively (_lib.iterator.require-
ments_). A template formal parameter with name C represents the set
of all possible instantiations on a parameter that satisfies the
requirements for a character on which any of the iostream components
can be instantiated. A template formal parameter with name Interna-
tional represents the set of all possible instantiations on a bool
parameter.
22.1.1.1.2 Class locale::facet [lib.locale.facet]
namespace std {
class locale::facet {
protected:
explicit facet(size_t refs = 0);
virtual ~facet();
private:
facet(const facet&); // not defined
void operator=(const facet&); // not defined
};
}
1 Class facet is the base class for locale feature sets. A class is a
facet if it is publicly derived from another facet, or if it is a
class derived from locale::facet and containing a publicly-accessible
declaration as follows:3)
static ::std::locale::id id;
Template parameters in this clause which are required to be facets are
those named Facet in declarations. A program that passes a type that
is not a facet, as an (explicit or deduced) template parameter to a
locale function expecting a facet, is ill-formed.
2 The refs argument to the constructor is used for lifetime management.
--For refs == 0, the implementation performs
delete static_cast<locale::facet*>(f) (where f is a pointer to the
facet) when the last locale object containing the facet is
destroyed; for refs == 1, the implementation never destroys the
facet.
+------- BEGIN BOX 2 -------+
This wording may require using "destroyed" instead of "deleted".
+------- END BOX 2 -------+
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
_________________________
3) This is a complete list of requirements; there are no other re-
quirements. Thus, a facet class need not have a public copy construc-
tor, assignment, default constructor, destructor, etc.
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 The class locale::id provides identification of a locale facet inter-
faces, used as an index for lookup and to encapsulate initialization.
2 [Note: Because facets are used by iostreams, potentially while static
constructors are running, their initialization cannot depend on pro-
grammed static initialization. One initialization strategy is for
locale to initialize each facet's id member the first time an instance
of the facet is installed into a locale. This depends only on static
storage being zero before constructors run (_basic.start.init_).
--end note]
22.1.1.2 locale constructors and destructor [lib.locale.cons]
locale() throw();
1 Default constructor: a snapshot of the current global locale.
Effects:
Constructs a copy of the argument last passed to
locale::global(locale&), if it has been called; else, the resulting
facets have virtual function semantics identical to those of
locale::classic(). [Note: This constructor is commonly used as the
default value for arguments of functions that take a const locale&
argument. --end note]
locale(const locale& other) throw();
Effects:
Constructs a locale which is a copy of other.
const locale& operator=(const locale& other) throw();
Effects:
Creates a copy of other, replacing the current value.
Returns:
*this
explicit locale(const char* std_name);
Effects:
Constructs a locale using standard C locale names, e.g. "POSIX".
The resulting locale implements semantics defined to be associated
with that name.
Throws:
runtime_error if the argument is not valid, or is null.
Notes:
The set of valid string argument values is "C", "", and any imple-
mentation-defined values.
locale(const locale& other, const char* std_name, category);
Effects:
Constructs a locale as a copy of other except for the facets identi-
fied by the category argument, which instead implement the same
semantics as locale(std_name).
Throws:
runtime_error if the argument is not valid, or is null.
Notes:
The locale has a name if and only if other has a name.
template <class Facet> locale(const locale& other, Facet* f);
Effects:
Constructs a locale incorporating all facets from the first argument
except that of type Facet, and installs the second argument as the
remaining facet. If f is null, the resulting object is a copy of
other.
Notes:
The resulting locale has no name.
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]
template <class Facet> locale combine(const locale& other);
Effects:
Constructs a locale incorporating all facets from *this except for
that one facet of other that is identified by Facet.
Returns:
The newly created locale.
Throws:
runtime_error if has_facet<Facet>(other) is false.
Notes:
The resulting locale has no name.
basic_string<char> name() const;
Returns:
The name of *this, if it has one; otherwise, the string "*". If
*this has a name, then locale(name()) is equivalent to *this.
Details of the contents of the resulting string are otherwise imple-
mentation-defined.
22.1.1.4 locale operators [lib.locale.operators]
bool operator==(const locale& other) const;
Returns:
true if both arguments are the same locale, or one is a copy of the
other, or each has a name and the names are identical; false other-
wise.
bool operator!=(const locale& other) const;
Returns:
The result of the expression: !(*this == other)
template <class charT, class Traits, class Allocator>
bool operator()(const basic_string<charT,Traits,Allocator>& s1,
const basic_string<charT,Traits,Allocator>& s2) const;
Effects:
Compares two strings according to the collate<charT> facet.
Notes:
This member operator template (and therefore locale itself) satis-
fies requirements for a comparator predicate template argument
(clause _lib.algorithms_) applied to strings.
Returns:
The result of the following expression:
use_facet< collate<charT> >(*this).compare(s1.data(), s1.data()+s1.size(),
s2.data(), s2.data()+s2.size()) < 0;
1 [Example: A vector of strings v can be collated according to collation
rules in locale loc simply by (_lib.alg.sort_, _lib.vector_):
std::sort(v.begin(), v.end(), loc);
--end example]
22.1.1.5 locale static members [lib.locale.statics]
static locale global(const locale& loc);
1 Sets the global locale to its argument.
Effects:
Causes future calls to the constructor locale() to return a copy of
the argument. If the argument has a name, does
std::setlocale(LC_ALL, loc.name().c_str());
otherwise, the effect on the C locale, if any, is implementation-
defined.
Returns:
The previous value of locale().
static const locale& classic();
2 The "C" locale.
Returns:
A locale that implements the classic "C" locale semantics, equiva-
lent to the value locale("C").
Notes:
This locale, its facets, and their member functions, do not change
with time.
22.1.2 locale globals [lib.locale.global.templates]
template <class Facet> const Facet& use_facet(const locale& loc);
1 Get a reference to a facet of a locale.
Returns:
a reference to the corresponding facet of loc, if present.
Throws:
bad_cast if has_facet<Facet>(loc) is false.
Notes:
The reference returned remains valid at least as long as any copy of
loc exists.
template <class Facet> bool has_facet(const locale& loc) throw();
Returns:
true if the facet requested is present in loc; otherwise false
22.1.3 Convenience interfaces [lib.locale.convenience]
22.1.3.1 Character classification [lib.classification]
template <class charT> bool isspace (charT c, const locale& loc);
template <class charT> bool isprint (charT c, const locale& loc);
template <class charT> bool iscntrl (charT c, const locale& loc);
template <class charT> bool isupper (charT c, const locale& loc);
template <class charT> bool islower (charT c, const locale& loc);
template <class charT> bool isalpha (charT c, const locale& loc);
template <class charT> bool isdigit (charT c, const locale& loc);
template <class charT> bool ispunct (charT c, const locale& loc);
template <class charT> bool isxdigit(charT c, const locale& loc);
template <class charT> bool isalnum (charT c, const locale& loc);
template <class charT> bool isgraph (charT c, const locale& loc);
1 Each of these functions isF returns the result of the expression:
use_facet< ctype<charT> >(loc).is(ctype_base::F, c)
where F is the ctype_base::mask value corresponding to that function
(_lib.category.ctype_).4)
22.1.3.2 Character conversions [lib.conversions]
template <class charT> charT toupper(charT c, const locale& loc) const;
Returns:
use_facet<ctype<charT> >(loc).toupper(c).
template <class charT> charT tolower(charT c, const locale& loc) const;
Returns:
use_facet<ctype<charT> >(loc).tolower(c).
22.2 Standard locale categories [lib.locale.categories]
1 Each of the standard categories includes a family of facets. Some of
these implement formatting or parsing of a datum, for use by standard
or users' iostream operators << and >>, as members put() and get(),
respectively. Each such member function takes an ios_base& argument
whose members flags(), precision(), and width(), specify the format of
the corresponding datum. (_lib.ios.base_). Those functions which
need to use other facets call its member getloc() to retrieve the
locale imbued there. Formatting facets use the character argument
_________________________
4) When used in a loop, it is faster to cache the ctype<> facet and
use it directly, or use the vector form of ctype<>::is.
fill to fill out the specified width where necessary.
2 The put() members make no provision for error reporting. (Any fail-
ures of the OutputIterator argument must be extracted from the
returned iterator.) The get() members take an ios_base::iostate&
argument whose value they ignore, but set to ios_base::failbit in case
of a parse error.
22.2.1 The ctype category [lib.category.ctype]
namespace std {
class ctype_base {
public:
enum mask { // numeric values are for exposition only.
space=1<<0, print=1<<1, cntrl=1<<2, upper=1<<3, lower=1<<4,
alpha=1<<5, digit=1<<6, punct=1<<7, xdigit=1<<8,
alnum=alpha|digit, graph=alnum|punct
};
};
}
1 The type mask is a bitmask type.
22.2.1.1 Template class ctype [lib.locale.ctype]
template <class charT>
class ctype : public locale::facet, public ctype_base {
public:
typedef charT char_type;
explicit ctype(size_t refs = 0);
bool is(mask m, charT c) const;
const charT* is(const charT* low, const charT* high, mask* vec) const;
const charT* scan_is(mask m,
const charT* low, const charT* high) const;
const charT* scan_not(mask m,
const charT* low, const charT* high) const;
charT toupper(charT c) const;
const charT* toupper(charT* low, const charT* high) const;
charT tolower(charT c) const;
const charT* tolower(charT* low, const charT* high) const;
charT widen(char c) const;
const char* widen(const char* low, const char* high, charT* to) const;
char narrow(charT c, char dfault) const;
const charT* narrow(const charT* low, const charT*, char dfault,
char* to) const;
static locale::id id;
protected:
~ctype(); // virtual
virtual bool do_is(mask m, charT c) const;
virtual const charT* do_is(const charT* low, const charT* high,
mask* vec) const;
virtual const charT* do_scan_is(mask m,
const charT* low, const charT* high) const;
virtual const charT* do_scan_not(mask m,
const charT* low, const charT* high) const;
virtual charT do_toupper(charT) const;
virtual const charT* do_toupper(charT* low, const charT* high) const;
virtual charT do_tolower(charT) const;
virtual const charT* do_tolower(charT* low, const charT* high) const;
virtual charT do_widen(char) const;
virtual const char* do_widen(const char* low, const char* high,
charT* dest) const;
virtual char do_narrow(charT, char dfault) const;
virtual const charT* do_narrow(const charT* low, const charT* high,
char dfault, char* dest) const;
};
1 Class ctype encapsulates the C library <cctype> features. istream
members are required to use ctype<> for character classing during
input parsing.
2 The instantiations required in Table 52, namely ctype<char> and
ctype<wchar_t>, implement character classing appropriate to the imple-
mentation's native character set.
+------- BEGIN BOX 3 -------+
Check the table number for "Table 52" hereafter.
+------- END BOX 3 -------+
22.2.1.1.1 ctype members [lib.locale.ctype.members]
bool is(mask m, charT c) const;
const charT* is(const charT* low, const charT* high,
mask* vec) const;
Returns:
do_is(m,c) or do_is(low,high,vec)
const charT* scan_is(mask m,
const charT* low, const charT* high) const;
Returns:
do_scan_is(m,low,high)
const charT* scan_not(mask m,
const charT* low, const charT* high) const;
Returns:
do_scan_not(m,low,high)
charT toupper(charT) const;
const charT* toupper(charT* low, const charT* high) const;
Returns:
do_toupper(c) or do_toupper(low,high)
charT tolower(charT c) const;
const charT* tolower(charT* low, const charT* high) const;
Returns:
do_tolower(c) or do_tolower(low,high)
charT widen(char c) const;
const char* widen(const char* low, const char* high, charT* to) const;
Returns:
do_widen(c) or do_widen(low,high,to)
char narrow(charT c, char dfault) const;
const charT* narrow(const charT* low, const charT*, char dfault,
char* to) const;
Returns:
do_narrow(c,dfault) or do_narrow(low,high,dfault,to)
22.2.1.1.2 ctype virtual functions [lib.locale.ctype.virtuals]
bool do_is(mask m, charT c) const;
const charT* do_is(const charT* low, const charT* high,
mask* vec) const;
Effects:
Classifies a character or sequence of characters. For each argument
character, identifies a value M of type ctype_base::mask. The sec-
ond form identifies a value M of type ctype_base::mask for each *p
where (low<=p && p<high), and places it into vec[p-low].
Returns:
The first form returns the result of the expression (M & m) != 0;
i.e., true if the character has the characteristics specified. The
second form returns high.
const charT* do_scan_is(mask m,
const charT* low, const charT* high) const;
Effects:
Locates a character in a buffer that conforms to a classification m.
Returns:
The smallest pointer p in the range [low, high) such that is(*p)
would return true; otherwise, returns high.
const charT* do_scan_not(mask m,
const charT* low, const charT* high) const;
Effects:
Locates a character in a buffer that fails to conform to a classifi-
cation m.
Returns:
The smallest pointer p, if any, in the range [low, high) such that
is(*p) would return false; otherwise, returns high.
charT do_toupper(charT c) const;
const charT* do_toupper(charT* low, const charT* high) const;
Effects:
Converts a character or characters to upper case. The second form
replaces each character *p in the range [low, high) for which a cor-
responding upper-case character exists, with that character.
Returns:
The first form returns the corresponding upper-case character if it
is known to exist, or its argument if not. The second form returns
high.
charT do_tolower(charT c) const;
const charT* do_tolower(charT* low, const charT* high) const;
Effects:
Converts a character or characters to lower case. The second form
replaces each character *p in the range [low, high) and for which a
corresponding lower-case character exists, with that character.
Returns:
The first form returns the corresponding lower-case character if it
is known to exist, or its argument if not. The second form returns
high.
charT do_widen(char c) const;
const char* do_widen(const char* low, const char* high,
charT* dest) const;
Effects:
Applies the simplest reasonable transformation from a char value or
sequence of char values to the corresponding charT value or
values.5) The only characters for which unique transformations are
required are those in the basic source character set
(_lex.charset_).
For any named ctype category with a ctype<charT> facet ctw and valid
ctype_base::mask value M (is(M, c) || !ctw.is(M, do_widen(c)) ) is
true.6)
The second form transforms each character *p in the range [low,
high), placing the result in dest[p-low].
Returns:
The first form returns the transformed value. The second form
returns high.
char do_narrow(charT c, char dfault) const;
const charT* do_narrow(const charT* low, const charT* high,
char dfault, char* dest) const;
Effects:
Applies the simplest reasonable transformation from a charT value or
sequence of charT values to the corresponding char value or values.
For any character c in the basic source character set(_lex.charset_)
the transformation is such that
do_widen(do_narrow(c),0) == c
For any named ctype category with a ctype<char> facet ctc however,
and ctype_base::mask value M,
(is(M,c) || !ctc.is(M, do_narrow(c),dfault) )"
is true (unless do_narrow returns dfault). In addition, for any
digit character c, the expression (do_narrow(c,dfault)-'0') evalu-
ates to the digit value of the character. The second form trans-
forms each character *p in the range [low, high), placing the result
(or dfault if no simple transformation is readly available) in
dest[p-low].
Returns:
The first form returns the transformed value; or dfault if no map-
ping is readily available. The second form returns high.
22.2.1.2 Template class ctype_byname [lib.locale.ctype.byname]
_________________________
5) The char argument of do_widen is intended to accept values derived
from character literals for conversion the locale's encoding.
6) In other words, the transformed character is not a member of any
character classification that c is not also a member of.
template <class charT>
class ctype_byname : public ctype<charT> {
public:
explicit ctype_byname(const char*, size_t refs = 0);
protected:
~ctype_byname(); // virtual
virtual bool do_is(mask m, charT c) const;
virtual const charT* do_is(const charT* low, const charT* high,
mask* vec) const;
virtual const char* do_scan_is(mask m,
const charT* low, const charT* high) const;
virtual const char* do_scan_not(mask m,
const charT* low, const charT* high) const;
virtual charT do_toupper(charT) const;
virtual const charT* do_toupper(charT* low, const charT* high) const;
virtual charT do_tolower(charT) const;
virtual const charT* do_tolower(charT* low, const charT* high) const;
virtual charT do_widen(char) const;
virtual const char* do_widen(const char* low, const char* high,
charT* dest) const;
virtual char do_narrow(charT, char dfault) const;
virtual const charT* do_narrow(const charT* low, const charT* high,
char dfault, char* dest) const;
};
}
22.2.1.3 ctype specializations [lib.facet.ctype.special]
namespace std {
template <> class ctype<char>
: public locale::facet, public ctype_base {
public:
typedef char char_type;
explicit ctype(const mask* tab = 0, bool del = false,
size_t refs = 0);
bool is(mask m, char c) const;
const char* is(const char* low, const char* high, mask* vec) const;
const char* scan_is (mask m,
const char* low, const char* high) const;
const char* scan_not(mask m,
const char* low, const char* high) const;
char toupper(char c) const;
const char* toupper(char* low, const char* high) const;
char tolower(char c) const;
const char* tolower(char* low, const char* high) const;
char widen(char c) const;
const char* widen(const char* low, const char* high, char* to) const;
char narrow(char c, char dfault) const;
const char* narrow(const char* low, const char* high, char dfault,
char* to) const;
static locale::id id;
static const size_t table_size = IMPLEMENTATION_DEFINED;
protected:
const mask* table() const throw();
static const mask* classic_table() throw();
~ctype(); // virtual
virtual char do_toupper(char c) const;
virtual const char* do_toupper(char* low, const char* high) const;
virtual char do_tolower(char c) const;
virtual const char* do_tolower(char* low, const char* high) const;
virtual char do_widen(char c) const;
virtual const char* do_widen(const char* low,
const char* high,
char* to) const;
virtual char do_narrow(char c, char dfault) const;
virtual const char* do_narrow(const char* low,
const char* high,
char dfault, char* to) const;
};
}
1 A specialization ctype<char> is provided so that the member functions
on type char can be implemented inline.7) The implementation-defined
value of member table_size is at least 256.
22.2.1.3.1 ctype<char> destructor [lib.facet.ctype.char.dtor]
~ctype();
Effects:
If the constructor's first argument was nonzero, and its second
argument was true, does delete [] table().
22.2.1.3.2 ctype<char> members [lib.facet.ctype.char.members]
1 In the following member descriptions, for unsigned char values v where
(v >= table_size), table()[v] is assumed to have an implementation-
defined value (possibly different for each such value v) without per-
forming the array lookup.
explicit ctype(const mask* tbl = 0, bool del = false,
size_t refs = 0);
Precondition:
tbl either 0 or an array of at least table_size elements.
Effects:
Passes its refs argument to its base class constructor.
_________________________
7) Only the char (not unsigned char and signed char) form is provided.
The specialization is specified in the standard, and not left as an
implementation detail, because it affects the derivation interface for
ctype<char>.
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;
Returns:
do_widen(low, high, to).
char narrow(char c, char /*dfault*/) const;
const char* narrow(const char* low, const char* high,
char /*dfault*/, char* to) const;
Returns:
do_narrow(low, high, to).
const mask* table() const throw();
Returns:
The first constructor argument, if it was non-zero, otherwise clas-
sic_table().
22.2.1.3.3 ctype<char> static [lib.facet.ctype.char.statics]
members
static const mask* classic_table() throw();
Returns:
A pointer to the initial element of an array of size table_size
which represents the classifications of characters in the "C"
locale.
22.2.1.3.4 ctype<char> virtual [lib.facet.ctype.char.virtuals]
functions
char do_toupper(char) const;
const char* do_toupper(char* low, const char* high) const;
char do_tolower(char) const;
const char* do_tolower(char* low, const char* high) const;
virtual char do_widen(char c) const;
virtual const char* do_widen(const char* low,
const char* high,
char* to) const;
virtual char do_narrow(char c, char dfault) const;
virtual const char* do_narrow(const char* low,
const char* high,
char dfault, char* to) const;
These functions are described identically as those members of the same
name in the ctype class template (_lib.locale.ctype.members_).
22.2.1.4 Class [lib.locale.ctype.byname.special]
ctype_byname<char>
template <> class ctype_byname<char> : public ctype<charT> {
public:
explicit ctype_byname(const char*, size_t refs = 0);
protected:
~ctype_byname(); // virtual
virtual char do_toupper(char c) const;
virtual const char* do_toupper(char* low, const char* high) const;
virtual char do_tolower(char c) const;
virtual const char* do_tolower(char* low, const char* high) const;
virtual char do_widen(char c) const;
virtual const char* do_widen(char* low,
const char* high,
char* to) const;
virtual char do_widen(char c) const;
virtual const char* do_widen(char* low,
const char* high) const;
};
}
1
22.2.1.5 Template class codecvt [lib.locale.codecvt]
namespace std {
class codecvt_base {
public:
enum result { ok, partial, error, noconv };
};
template <class internT, class externT, class stateT>
class codecvt : public locale::facet, public codecvt_base {
public:
typedef internT intern_type;
typedef externT extern_type;
typedef stateT state_type;
explicit codecvt(size_t refs = 0)
result out(stateT& state,
const internT* from, const internT* from_end, const internT*& from_next,
externT* to, externT* to_limit, externT*& to_next) const;
result unshift(stateT& state,
externT* to, externT* to_limit, externT*& to_next) const;
result in(stateT& state,
const externT* from, const externT* from_end, const externT*& from_next,
internT* to, internT* to_limit, internT*& to_next) const;
int encoding() const throw();
bool always_noconv() const throw();
int length(const stateT&, const externT* from, const externT* end,
size_t max) const;
int max_length() const throw();
static locale::id id;
protected:
~codecvt(); // virtual
virtual result do_out(stateT& state,
const internT* from, const internT* from_end, const internT*& from_next,
externT* to, externT* to_limit, externT*& to_next) const;
virtual result do_in(stateT& state,
const externT* from, const externT* from_end, const externT*& from_next,
internT* to, internT* to_limit, internT*& to_next) const;
virtual result do_unshift(stateT& state,
externT* to, externT* to_limit, externT*& to_next) const;
virtual int do_encoding() const throw();
virtual bool do_always_noconv() const throw();
virtual int do_length(const stateT&, const externT* from, const externT* end,
size_t max) const;
virtual int do_max_length() const throw();
};
}
1 The class codecvt<internT,externT,stateT> is for use when converting
from one codeset to another, such as from wide characters to multibyte
characters, between wide character encodings such as Unicode and EUC.
2 The stateT argument selects the pair of codesets being mapped between.
3 The instantiations required in Table 52, namely
codecvt<wchar_t,char,mbstate_t> and codecvt<char,char,mbstate_t>, con-
vert the implementation-defined native character set.
codecvt<char,char,mbstate_t> implements a degenerate conversion; it
does not convert at all. codecvt<wchar_t,char,mbstate_t> converts
between the native character sets for tiny and wide characters.
Instantiations on mbstate_t perform conversion between encodings known
to the library implementor. Other encodings can be converted by spe-
cializing on a user-defined stateT type. The stateT object can con-
tain any state that is useful to communicate to or from the special-
ized do_convert member.
22.2.1.5.1 codecvt members [lib.locale.codecvt.members]
result out(stateT& state,
const internT* from, const internT* from_end, const internT*& from_next,
externT* to, externT* to_limit, externT*& to_next) const;
Returns:
do_out(state, from, from_end, from_next, to,to_limit, to_next)
result unshift(stateT& state,
externT* to, externT* to_limit, externT*& to_next) const;
Returns:
do_unshift(state, to, to_limit, to_next)
result in(stateT& state,
const externT* from, const externT* from_end, const externT*& from_next,
internT* to, internT* to_limit, internT*& to_next) const;
Returns:
do_in(state, from,from_end,from_next, to,to_limit,to_next)
int encoding() const throw();
Returns:
do_encoding()
bool always_noconv() const throw();
Returns:
do_always_noconv()
int length(stateT& state, const externT* from, const externT* from_end,
size_t max) const;
Returns:
do_length(state, from,from_end,max)
int max_length() const throw();
Returns:
do_max_length()
22.2.1.5.2 codecvt virtual [lib.locale.codecvt.virtuals]
functions
result do_out(stateT& state,
const internT* from, const internT* from_end, const internT*& from_next,
externT* to, externT* to_limit, externT*& to_next) const;
result do_in(stateT& state,
const externT* from, const externT* from_end, const externT*& from_next,
internT* to, internT* to_limit, internT*& to_next) const;
Preconditions:
(from<=from_end && to<=to_end) well-defined and true; state initial-
ized, if at the beginning of a sequence, or else equal to the result
of converting the preceding characters in the sequence.
Effects:
Translates characters in the source range [from,from_end), placing
the results in sequential positions starting at destination to.
Converts no more than (from_end-from) source elements, and stores no
more than (to_limit-to) destination elements.
Stops if it encounters a character it cannot convert. It always
leaves the from_next and to_next pointers pointing one beyond the
last element successfully converted. [Note: If no translation is
needed (returns noconv), sets to_next equal to argument to, and
from_next equal to argument from. --end note]
Notes:
Its operations on state are unspecified.
[Note: This argument can be used, for example, to maintain shift
state, to specify conversion options (such as count only), or to
identify a cache of seek offsets. --end note]
Returns:
An enumeration value, as summarized in Table 4:
Table 4--convert result values
+-----------------------------------------------------------------+
| Value Meaning |
+-----------------------------------------------------------------+
|ok completed the conversion |
|partial not all source characters converted |
|error encountered a from_type character it could not convert |
|noconv no conversion was needed |
+-----------------------------------------------------------------+
A return value of partial, if (from_next==from_end), indicates that
either the destination sequence has not absorbed all the available
destination elements, or that additional source elements are needed
before another destination element can be produced.
result do_unshift(stateT& state,
externT* to, externT* to_limit, externT*& to_next) const;
Effects
Places characters starting at to that should be appended to termi-
nate a sequence when the current stateT is given by state.8) The
instantiations required in Table 52, namely
codecvt<wchar_t,char,mbstate_t> and codecvt<char,char,mbstate_t>,
store no characters. Stores no more than (to_limit-to) destination
elements. It always leaves the to_next pointer pointing one beyond
the last element successfully stored.
Returns
An enumeration value, as summarized in Table 5:
_________________________
8) Typically these will be characters to return the state to stateT()
Table 5--convert result values
+----------------------------------------------------------------------+
| Value Meaning |
+----------------------------------------------------------------------+
|ok completed the sequence |
|partial more characters need to be supplied to complete termination |
|error state has invalid value. |
|noconv no termination is needed for this state_type |
+----------------------------------------------------------------------+
codecvt<char,char,mbstate_t>, returns noconv.
int do_encoding() const throw();
Returns:
-1 if the encoding of the externT sequence is state-dependent; else
the constant number of externT characters needed to produce an
internal character; or 0 if this number is not a constant9).
bool do_always_noconv() const throw();
Returns:
true if do_convert() returns noconv for all valid argument values.
codecvt<char,char,mbstate_t> returns true.
int do_length(stateT& state, const externT* from, const externT* from_end,
size_t max) const;
Preconditions:
(from<=from_end) well-defined and true; state initialized, if at the
beginning of a sequence, or else equal to the result of converting
the preceding characters in the sequence.
Returns:
(from_next-from) where from_next is the largest value in the range
[from,from_end] such that the sequence of values in the range
[from,from_next) represents max or fewer valid complete characters
of type internT. The instantiations required in Table 52, namely
codecvt<wchar_t,char,mbstate_t> and codecvt<char,char,mbstate_t>,
return the lesser of max and (from_end-from).
_________________________
9) If encoding() yields -1, then more than max_length() externT ele-
ments may be consumed when producing a single internT character, and
additional externT elements may appear at the end of a sequence after
those that yield the final internT character.
int do_max_length() const throw();
Returns:
The maximum value that do_length(state,from,from_end,1) can return
for any valid range [from,from_end) and stateT value state.
codecvt<char,char,mbstate_t> returns 1.
22.2.1.6 Template class [lib.locale.codecvt.byname]
codecvt_byname
namespace std {
template <class internT, class externT, class stateT>
class codecvt_byname : public codecvt<internT, externT, stateT> {
public:
explicit codecvt_byname(const char*, size_t refs = 0);
protected:
~codecvt_byname(); // virtual
virtual result do_out(stateT& state,
const internT* from, const internT* from_end, const internT*& from_next,
externT* to, externT* to_limit, externT*& to_next) const;
virtual result do_in(stateT& state,
const externT* from, const externT* from_end, const externT*& from_next,
internT* to, internT* to_limit, internT*& to_next) const;
virtual result do_unshift(stateT& state,
externT* to, externT* to_limit, externT*& to_next) const;
virtual int do_encoding() const throw();
virtual bool do_always_noconv() const throw();
virtual int do_length(const stateT&, const externT* from, const externT* end,
size_t max) const;
virtual result do_unshift(stateT& state,
externT* to, externT* to_limit, externT*& to_next) const;
virtual int do_max_length() const throw();
};
}
22.2.2 The numeric category [lib.category.numeric]
1 The classes num_get<> and num_put<> handle numeric formatting and
parsing. Virtual functions are provided for several numeric types.
Implementations may (but are not required to) delegate extraction of
smaller types to extractors for larger types.10)
2 All specifications of member functions for num_put and num_get in the
subclauses of _lib.category.numeric_ only apply to the instantiations
required in Table 52 and Table 53, namely num_get<char>,
num_get<wchar_t>, num_get<C,InputIterator>, num_put<char>,
num_put<wchar_t>, and num_put<C,OutputIterator>. These instantiations
refer to the ios_base& argument for formatting specifications
(_lib.locale.categories_), and to its imbued locale for the numpunct<>
_________________________
10) Parsing "-1" correctly into (e.g.) an unsigned short requires that
the corresponding member get() at least extract the sign before dele-
gating.
facet to identify all numeric punctuation preferences, and also for
the ctype<> facet to perform character classification.
3 Extractor and inserter members of the standard iostreams use num_get<>
and num_put<> member functions for formatting and parsing numeric val-
ues (_lib.istream.formatted.reqmts_, _lib.ostream.formatted.reqmts_).
22.2.2.1 Template class num_get [lib.locale.num.get]
namespace std {
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class num_get : public locale::facet {
public:
typedef charT char_type;
typedef InputIterator iter_type;
explicit num_get(size_t refs = 0);
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, bool& v) const;
iter_type get(iter_type in, iter_type end, ios_base& ,
ios_base::iostate& err, long& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, unsigned short& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, unsigned int& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, unsigned long& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, float& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, double& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, long double& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, void*& v) const;
static locale::id id;
protected:
~num_get(); // virtual
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, bool& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, long& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, unsigned short& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, unsigned int& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, unsigned long& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, float& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, double& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, long double& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, void*& v) const;
};
}
1 The facet num_get is used to parse numeric values from an input
sequence such as an istream.
22.2.2.1.1 num_get members [lib.facet.num.get.members]
iter_type get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, long& val) const;
iter_type get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, unsigned short& val) const;
iter_type get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, unsigned int& val) const;
iter_type get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, unsigned long& val) const;
iter_type get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, short& val) const;
iter_type get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, double& val) const;
iter_type get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, long double& val) const;
iter_type get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, void*& val) const;
Returns:
do_get(in, end, str, err, val).
22.2.2.1.2 num_get virtual [lib.facet.num.get.virtuals]
functions
iter_type do_get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, long& val) const;
iter_type do_get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, unsigned short& val) const;
iter_type do_get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, unsigned int& val) const;
iter_type do_get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, unsigned long& val) const;
iter_type do_get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, float& val) const;
iter_type do_get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, double& val) const;
iter_type do_get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, long double& val) const;
iter_type do_get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, void*& val) const;
Effects:
Reads characters from in, interpreting them according to
str.flags(), use_facet< ctype<charT> >(loc), and use_facet<
numpunct<charT> >(loc), where loc is str.getloc(). If an error
occurs, val is unchanged; otherwise it is set to the resulting
value.
1 The details of this operation occur in three stages
--Stage 1: Determine a conversion specifier
--Stage 2: Extract characters from in and transform them into char's,
converting the value transformed characters according to the conver-
sion specification determined in stage 1.
--Stage 3: Store results
The details of the stages are presented below. in.
Stage 1:
The function initializes local variables via
fmtflags flags = str.flags();
fmtflags basefield = (flags & ios_base::basefield);
fmtflags uppercase = (flags & ios_base::uppercase);
fmtflags boolalpha = (flags & ios_base::boolalpha);
For conversion to an integral type, the function determines the
integral conversion specifier as indicated in Table 6. The table is
ordered. That is, the first line whose condition is true applies.
Table 6--Integer conversions
+------------------------------------------+
| State stdio equivalent |
+------------------------------------------+
|basefield == oct %o |
+------------------------------------------+
|basefield == hex %X |
+------------------------------------------+
|basefield == 0 %i |
+------------------------------------------+
|signed integral type %d |
+------------------------------------------+
|unsigned integral type %u |
+------------------------------------------+
For conversions to a floating type the specifier is %g.
For conversions to void* the specifier is %p.
A length specifier is added to the conversion specification, if
needed, as indicated in Table 7.
Table 7--Length Modifier
+---------------------------------+
| type length modifier |
+---------------------------------+
|short h |
+---------------------------------+
|unsigned short h |
+---------------------------------+
|long l |
+---------------------------------+
|unsigned long l |
+---------------------------------+
|long double L |
+---------------------------------+
Stage 2:
If in==end then stage 2 terminates. Otherwise a charT is taken from
in and local variables are initialized as if by
+------- BEGIN BOX 4 -------+
Re-write without "narrow", as per 22-002 - NCM.
+------- END BOX 4 -------+
char_type ct = *in ;
char c = use_facet<ctype<charT> >(loc).narrow(ct,' ');
if ( ct == use_facet<numpunct<charT> >(loc).decimal_point() )
c = '.';
bool discard =
( ct == use_facet<numpunct<charT> >(loc).thousands_sep()
&&
use_facet<numpunct<charT> >(loc).grouping().length() != 0 );
If discard is true then the position of the character is remembered,
but the character is otherwise ignored. If it is not discarded,
then a check is made to determine if c is allowed as the next char-
acter of an input field of the conversion specifier returned by
stage 1. If so it is accumulated.
If the character is either discarded or accumulated then in is
advanced by ++in and processing returns to the beginning of stage 2.
Stage 3:
The result of stage 2 processing can be one of
--A sequence of chars has been accumulated in stage 2 that is con-
verted (according to the rules of scanf) to a value of the type of
val. This value is stored in val and ios_base::goodbit is stored in
err.
--The sequence of chars accumulated in stage 2 would have caused scanf
to report an input failure. ios_base::failbit is assigned to err.
2 Digit grouping is checked. That is, the positions of discarded sepa-
rators is examined for consistency with use_facet<numpunct<charT>
>(loc).grouping(). If they are not consistent then ios_base::failbit
is assigned to err.
3 In any case, if stage 2 processing was terminated by the test for
in==end then err|=ios_base::eofbit is performed.
iter_type do_get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, bool& val) const;
Effects:
If (str.flags()&&ios_base::boolalpha)==0 then input proceeds as it
would for a long except that if a value is being stored into val,
the value is determined according to the following: If the value to
be stored is 0 then false is stored. If the value is 1 then true is
stored. Otherwise err|=ios_base::failbit is performed and no value
is stored.
4 Otherwise a target string to be matched is determined by calling
either use_facet<ctype<charT> >(loc).truename() or
use_facet<ctype<charT> >(loc).falsename() depending on whether val is
true or false (respectively).
5 As long as in!=end and characters continue to match the target string
charT's are obtained by doing *in++. A value is assigned to err as
follows
--If the target string was matched completely, then goodbit.
--If input was terminated because in!=end, then eofbit
--Otherwise, failbit.
Returns:
in.
22.2.2.2 Template class num_put [lib.locale.nm.put]
namespace std {
template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
class num_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
explicit num_put(size_t refs = 0);
iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const;
iter_type put(iter_type s, ios_base& f, char_type fill, long v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
unsigned long v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
double v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
long double v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
void* v) const;
static locale::id id;
protected:
~num_put(); // virtual
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
bool v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
long v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
unsigned long) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
double v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
long double v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
void* v) const;
};
}
1 The facet num_put is used to format numeric values to a character
sequence such as an ostream.
22.2.2.2.1 num_put members [lib.facet.num.put.members]
iter_type put(iter_type out, ios_base& str, char_type fill,
bool val) const;
iter_type put(iter_type out, ios_base& str, char_type fill,
long val) const;
iter_type put(iter_type out, ios_base& str, char_type fill,
unsigned long val) const;
iter_type put(iter_type out, ios_base& str, char_type fill,
double val) const;
iter_type put(iter_type out, ios_base& str, char_type fill,
long double val) const;
iter_type put(iter_type out, ios_base& str, char_type fill,
void* val) const;
Returns:
do_put(out, str, fill, val).
22.2.2.2.2 num_put virtual [lib.facet.num.put.virtuals]
functions
iter_type do_put(iter_type out, ios_base& str, char_type fill,
bool val) const;
iter_type do_put(iter_type out, ios_base& str, char_type fill,
long val) const;
iter_type do_put(iter_type out, ios_base& str, char_type fill,
unsigned long val) const;
iter_type do_put(iter_type out, ios_base& str, char_type fill,
double val) const;
iter_type do_put(iter_type out, ios_base& str, char_type fill,
long double val) const;
iter_type do_put(iter_type out, ios_base& str, char_type fill,
void* val) const;
Effects:
Writes characters to the sequence out, formatting val as desired.
In the following description, a local variable initialized with
locale loc = str.getloc();
1 The details of this operation occur in several stages:
--Stage 1: Determine a printf conversion specifier spec and determin-
ing the characters that would be printed by printf(_lib.c.files_)
given this conversion specifier for
printf(spec, val)
assuming that the current locale is the "C" locale.
--Stage 2: Adjust the representation by converting each char deter-
mined by stage 1 to a charT using a conversion and values returned
by members of use_facet< numpunct<charT> >(str.getloc())
--Stage 3: Determine where padding is required.
--Stage 4: Insert the sequence into the out.
Detailed descriptions of each stage follow.
Returns:
out.
Stage 1:
The first action of stage 1 is to determine a conversion specifier.
The tables that describe this determination use the following local
variables
fmtflags flags = str.flags() ;
fmtflags basefield = (flags & (ios_base::basefield));
fmtflags uppercase = (flags & (ios_base::uppercase));
fmtflags floatfield = (flags & (ios_base::floatfield));
fmtflags showpos = (flags & (ios_base::showpos));
fmtflags showbase = (flags & (ios_base::showbase));
All tables used in describing stage 1 are ordered. That is, the
first line whose condition is true applies. A line without a condi-
tion is the default behavior when none of the earlier lines apply.
For conversion from an integral type other than a character type,
the function determines the integral conversion specifier as indi-
cated in Table 8.
Table 8--Integer conversions
+---------------------------------------------------------------+
| State stdio equivalent |
+---------------------------------------------------------------+
|basefield == ios_base::oct %o |
+---------------------------------------------------------------+
|(basefield == ios_base::hex) && !uppercase %x |
+---------------------------------------------------------------+
|(basefield == ios_base::hex) %X |
+---------------------------------------------------------------+
|for a signed integral type %d |
+---------------------------------------------------------------+
|for an unsigned integral type %u |
+---------------------------------------------------------------+
For conversion from a floating-point type, the function determines
the floating-point conversion specifier as indicated in Table 9:
Table 9--Floating-point conversions
+--------------------------------------------------------------------+
| State stdio equivalent |
+--------------------------------------------------------------------+
|floatfield == ios_base::fixed %f |
+--------------------------------------------------------------------+
|floatfield == ios_base::scientific && !uppercase %e |
+--------------------------------------------------------------------+
|floatfield == ios_base::scientific %E |
+--------------------------------------------------------------------+
|!uppercase %g |
+--------------------------------------------------------------------+
|otherwise %G |
+--------------------------------------------------------------------+
For conversions from an integral or floating type a length modifier
is added to the conversion specifier as indicated in Table 10.
Table 10--Length modifier
+--------------------------------+
| type length modifier |
+--------------------------------+
|long l |
+--------------------------------+
|unsigned long l |
+--------------------------------+
|long double L |
+--------------------------------+
|otherwise none |
+--------------------------------+
The conversion specifier has the following optional additional qual-
ifiers prepended as indicated in Table 11:
Table 11--Numeric conversions
+--------------------------------------------------------------+
| Type(s) State stdio equivalent |
+--------------------------------------------------------------+
|an integral type flags & showpos + |
| flags & showbase # |
+--------------------------------------------------------------+
|a floating-point type flags & showpos + |
| flags & showpoint # |
+--------------------------------------------------------------+
For conversion from a floating-point type, if (flags & fixed) != 0
or if str.precision() > 0, then str.precision() is specified in the
conversion specification.
For conversion from void* the specifier is %p.
The representations at the end of stage 1 consists of the char's
that would be printed by a call of printf(s, val) where s is the
conversion specifier determined above.
Stage 2:
Any character c other than a decimal point(.) is converted to a
charT via use_facet<ctype<charT> >(loc).widen(c)
2 A local variable punct is initialized via
numpunct<charT> punct = use_facet< numpunct<charT> >(str.getloc())
For integral types, punct.thousands_sep() characters are inserted
into the sequence as determined by the value returned by
punct.do_grouping() using the method described in
_lib.facet.numpunct.virtuals_
Decimal point characters(.) are replaced by punct.decimal_point()
Stage 3:
A local variable is initialized as
fmtflags adjustfield= (flags & (ios_base::adjustfield));
The location of any padding11) is determined according to Table 12:
Table 12--Fill padding
+----------------------------------------------------+
| State Location |
+----------------------------------------------------+
|adjustfield == ios_base::left pad after |
+----------------------------------------------------+
|adjustfield == ios_base::right pad before |
+----------------------------------------------------+
|adjustfield == internal and a pad after the sign |
|sign occurs in the representa- |
|tion |
+----------------------------------------------------+
|adjustfield == internal and pad after x or X |
|representation after stage 1 |
|began with 0x 1or 0X |
+----------------------------------------------------+
|otherwise pad before |
+----------------------------------------------------+
If str.width() is nonzero and the number of charT's in the sequence
after stage 2 is less than str.width(), then enough fill characters
are added to the sequence at the position indicated for padding to
_________________________
11) The conversion specification #o generates a leading 0 which is not
a padding character.
bring the length of the sequence to str.width().
str.width(0) is called.
Stage 4:
The sequence of charT's at the end of stage 3 are output via
*out++ = c
iter_type put(iter_type out, ios_base& str, char_type fill,
bool val) const;
Effects:
If (str.flags()&ios_base::boolalpha)==0 then do
out = do_put(out, str, fill, (int)val)
Otherwise do
string_type s =
val ? use_facet<ctype<charT> >(loc).truename()
: use_facet<ctype<charT> >(loc).falsename() ;
and then insert the characters of s into out. out.
22.2.3 The numeric punctuation facet [lib.facet.numpunct]
22.2.3.1 Template class numpunct [lib.locale.numpunct]
namespace std {
template <class charT>
class numpunct : public locale::facet {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit numpunct(size_t refs = 0);
char_type decimal_point() const;
char_type thousands_sep() const;
string grouping() const;
string_type truename() const;
string_type falsename() const;
static locale::id id;
protected:
~numpunct(); // virtual
virtual char_type do_decimal_point() const;
virtual char_type do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_truename() const; // for bool
virtual string_type do_falsename() const; // for bool
};
}
1 numpunct<> specifies numeric punctuation. The instantiations required
in Table 52, namely numpunct<wchar_t> and numpunct<char>, provide
classic C" numeric formats, i.e. they contain information equivalent
to that contained in the C" locale or their wide character counter-
parts as if obtained by a call to widen.
2 The syntax for number formats is as follows, where digit represents
the radix set specified by the fmtflags argument value, whitespace is
as determined by the facet ctype<charT> (_lib.locale.ctype_), and
thousands-sep and decimal-point are the results of corresponding
numpunct<charT> members. Integer values have the format:
integer ::= [sign] units
sign ::= plusminus [whitespace]
plusminus ::= '+' | '-'
units ::= digits [thousands-sep units]
digits ::= digit [digits]
and floating-point values have:
floatval ::= [sign] units [decimal-point [digits]] [e [sign] digits] |
[sign] decimal-point digits [e [sign] digits]
e ::= 'e' | 'E'
where the number of digits between thousands-seps is as specified by
do_grouping(). For parsing, if the digits portion contains no thou-
sands-separators, no grouping constraint is applied.
+------- BEGIN BOX 5 -------+
Note: The above text does not describe any behavior of numpunct<> and
is not referred to anywhere else in the Draft, and should be deleted.
+------- END BOX 5 -------+
22.2.3.1.1 numpunct members [lib.facet.numpunct.members]
char_type decimal_point() const;
Returns:
do_decimal_point()
char_type thousands_sep() const;
Returns:
do_thousands_sep()
string grouping() const;
Returns:
do_grouping()
string_type truename() const;
string_type falsename() const;
Returns:
do_truename() or do_falsename(), respectively.
22.2.3.1.2 numpunct virtual [lib.facet.numpunct.virtuals]
functions
char_type do_decimal_point() const;
Returns:
A character for use as the decimal radix separator. The required
instantiations return '.' or L'.'.
string_type do_thousands_sep() const;
Returns:
A character for use as the digit group separator. The required
instantiations return ',' or L','.
string do_grouping() const;
Returns:
A basic_string<char> vec used as a vector of integer values, in
which each element vec[i] represents the number of digits12) in the
group at position i, starting with position 0 as the rightmost
group. If vec.size() <= i, the number is the same as group (i-1);
if (i<0 || vec[i]<=0 || vec[i]==CHAR_MAX), the size of the digit
group is unlimited.
The required instantiations return the empty string, indicating no
grouping.
string_type do_truename() const;
string_type do_falsename() const;
Returns:
A string representing the name of the boolean value true or false,
respectively.
In the base class implementation these names are "true" and "false",
or L"true" and L"false".
22.2.3.2 Template class [lib.locale.numpunct.byname]
numpunct_byname
_________________________
12) Thus, the string "\003" specifies groups of 3 digits each, and "3"
probably indicates groups of 51 (!) digits each, because 51 is the
ASCII value of "3".
namespace std {
template <class charT>
class numpunct_byname : public numpunct<charT> {
// this class is specialized for char and wchar_t.
public:
explicit numpunct_byname(const char*, size_t refs = 0);
protected:
~numpunct_byname(); // virtual
virtual char_type do_decimal_point() const;
virtual char_type do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_truename() const; // for bool
virtual string_type do_falsename() const; // for bool
};
}
22.2.4 The collate category [lib.category.collate]
22.2.4.1 Template class collate [lib.locale.collate]
namespace std {
template <class charT>
class collate : public locale::facet {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit collate(size_t refs = 0);
int compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
string_type transform(const charT* low, const charT* high) const;
long hash(const charT* low, const charT* high) const;
static locale::id id;
protected:
~collate(); // virtual
virtual int do_compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
virtual string_type do_transform(const charT* low, const charT* high) const;
virtual long do_hash (const charT* low, const charT* high) const;
};
}
1 The class collate<charT> provides features for use in the collation
(comparison) and hashing of strings. A locale member function tem-
plate, operator(), uses the collate facet to allow a locale to act
directly as the predicate argument for standard algorithms (clause
_lib.algorithms_) and containers operating on strings. The instantia-
tions required in Table 52, namely collate<char> and collate<wchar_t>,
apply lexicographic ordering (_lib.alg.lex.comparison_).
2 Each function compares a string of characters *p in the range
[low,high).
22.2.4.1.1 collate members [lib.locale.collate.members]
int compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
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 instantiations required in Table 52, namely col-
late<char> and collate<wchar_t>, implement a lexicographical compar-
ison (_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.13)
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
_________________________
13) This function is useful when one string is being compared to many
other strings.
another string which does not compare equal should be very small,
approaching (1.0/numeric_limits<unsigned long>::max()). --end
note]
22.2.4.2 Template class [lib.locale.collate.byname]
collate_byname
namespace std {
template <class charT>
class collate_byname : public collate<charT> {
public:
explicit collate_byname(const char*, size_t refs = 0);
protected:
~collate_byname(); // virtual
virtual int do_compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
virtual string_type do_transform(const charT* low, const charT* high) const;
virtual long do_hash( const charT* low, const charT* high) const;
};
22.2.5 The time category [lib.category.time]
1 Templates time_get<charT,InputIterator> and time_put<charT,OutputIter-
ator> provide date and time formatting and parsing.
+------- BEGIN BOX 6 -------+
The effect of the ios_base argument to member functions of time_put
and time_get is unspecified. Do they have any effect at all? Which
format flags are ignored? Or is it undefined, or implementation-depen-
dent?
Actually, the same is true for the monetary facets. For instance, do
the dec, hex, oct flags have any effect on the formatting of monetary
amounts, or is it implementation-dependent whether they have an
effect?
Date/time and money formats are implementation-defined.
+------- END BOX 6 -------+
All specifications of member functions for time_put and time_get in
the subclauses of _lib.category.time_ only apply to the instantiations
required in Table 52 and Table 53. Their members use their ios_base&,
ios_base::iostate&, and fill arguments as described in
(_lib.locale.categories_), and the ctype<> facet, to determine format-
ting details.
22.2.5.1 Template class time_get [lib.locale.time.get]
namespace std {
class time_base {
public:
enum dateorder { no_order, dmy, mdy, ymd, ydm };
};
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class time_get : public locale::facet, public time_base {
public:
typedef charT char_type;
typedef InputIterator iter_type;
explicit time_get(size_t refs = 0);
dateorder date_order() const { return do_date_order(); }
iter_type get_time(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;
iter_type get_date(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;
iter_type get_weekday(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;
iter_type get_monthname(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;
iter_type get_year(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;
static locale::id id;
protected:
~time_get(); // virtual
virtual dateorder do_date_order() const;
virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_monthname(iter_type s, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
};
}
1 time_get is used to parse a character sequence, extracting components
of a time or date into a struct tm record. Each get member parses a
format as produced by a corresponding format specifier to
time_put<>::put. If the sequence being parsed matches the correct
format, the corresponding members of the struct tm argument are set to
the values used to produce the sequence; otherwise either an error is
reported or unspecified values are assigned.14)
_________________________
14) In other words, user confirmation is required for reliable parsing
of user-entered dates and times, but machine-generated formats can be
parsed reliably. This allows parsers to be aggressive about inter-
preting user variations on standard formats.
22.2.5.1.1 time_get members [lib.locale.time.get.members]
dateorder date_order() const;
Returns:
do_date_order()
iter_type get_time(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
Returns:
do_get_time(s, end, str, err, t)
iter_type get_date(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
Returns:
do_get_date(s, end, str, err, t)
iter_type get_weekday(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
iter_type get_monthname(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
Returns:
do_get_weekday(s, end, str, err, t) or do_get_monthname(s, end, str,
err, t)
iter_type get_year(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
Returns:
do_get_year(s, end, str, err, t)
22.2.5.1.2 time_get virtual [lib.locale.time.get.virtuals]
functions
dateorder do_date_order() const;
Returns:
An enumeration value indicating the preferred order of components
for those date formats that are composed of day, month, and year.15)
Returns no_order if the date format specified by 'x' contains other
_________________________
15) This function is intended as a convenience only, for common for-
mats, and may return no_order in valid locales.
variable components (e.g. Julian day, week number, week day).
iter_type do_get_time(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
Effects:
Reads characters starting at s until it has extracted those struct
tm members, and remaining format characters, used by time_put<>::put
to produce the format specified by 'X', or until it encounters an
error or end of sequence.
Returns:
An iterator pointing immediately beyond the last character recog-
nized as possibly part of a valid time.
iter_type do_get_date(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
Effects:
Reads characters starting at s until it has extracted those struct
tm members, and remaining format characters, used by time_put<>::put
to produce the format specified by 'x', or until it encounters an
error.
Returns:
An iterator pointing immediately beyond the last character recog-
nized as possibly part of a valid date.
iter_type do_get_weekday(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
iter_type do_get_monthname(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
Effects:
Reads characters starting at s until it has extracted the (perhaps
abbreviated) name of a weekday or month. If it finds an abbrevia-
tion that is followed by characters that could match a full name, it
continues reading until it matches the full name or fails. It sets
the appropriate struct tm member accordingly.
Returns:
An iterator pointing immediately beyond the last character recog-
nized as part of a valid name.
iter_type do_get_year(iter_type s, iter_type end, ios_base& str,
ios_base::iostate& err, tm* t) const;
Effects:
Reads characters starting at s until it has extracted an unambiguous
year identifier. It is implementation-defined whether two-digit
year numbers are accepted, and (if so) what century they are assumed
to lie in. Sets the t->tm_year member accordingly.
Returns:
An iterator pointing immediately beyond the last character recog-
nized as part of a valid year identifier.
22.2.5.2 Template class [lib.locale.time.get.byname]
time_get_byname
namespace std {
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class time_get_byname : public time_get<charT, InputIterator> {
public:
explicit time_get_byname(const char*, size_t refs = 0);
protected:
~time_get_byname(); // virtual
virtual dateorder do_date_order() const;
virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_monthname(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
};
}
22.2.5.3 Template class time_put [lib.locale.time.put]
namespace std {
template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
class time_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
explicit time_put(size_t refs = 0);
// the following is implemented in terms of other member functions.
iter_type put(iter_type s, ios_base& f, char_type fill, const tm* tmb,
const charT* pattern, const charT* pat_end) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
const tm* tmb, char format, char modifier = 0) const;
static locale::id id;
protected:
~time_put(); // virtual
virtual iter_type do_put(iter_type s, ios_base&, char_type, const tm* t,
char format, char modifier) const;
};
}
22.2.5.3.1 time_put members [lib.locale.time.put.members]
iter_type put(iter_type s, ios_base& str, char_type fill, const tm* t,
const charT* pattern, const charT* pat_end) const;
iter_type put(iter_type s, ios_base& str, char_type fill, const tm* t,
char format, char modifier = 0) const;
Effects:
The first form steps through the sequence from pattern to end, iden-
tifying characters that are part of a format sequence. Each charac-
ter that is not part of a format sequence is written to s immedi-
ately, and each format sequence, as it is identified, results in a
call to do_put; thus, format elements and other characters are
interleaved in the output in the order in which they appear in the
pattern. Format sequences are identified by converting each charac-
ter c to a char value as if by ct.narrow(c, 0), where ct is a refer-
ence to ctype<charT> obtained from str.getloc(). The first charac-
ter of each sequence is equal to '%', followed by an optional modi-
fier character mod16) and a format specifier character spec as
defined for the function strftime. If no modifier character is pre-
sent, mod is zero. For each valid format sequence identified, calls
do_put(s, str, fill, t, spec, mod).
1 The second form calls do_put(s, str, fill, t, format, modifier).
Returns:
An iterator pointing immediately after the last character produced.
22.2.5.3.2 time_put virtual [lib.locale.time.put.virtuals]
functions
iter_type do_put(iter_type s, ios_base&, char_type fill, const tm* t,
char format, char modifier) const;
Effects:
Formats the contents of the parameter t into characters placed on
the output sequence s. Formatting is controlled by the parameters
format and modifier, interpreted identically as the format speci-
fiers in the string argument to the standard library function
strftime().17) except that the sequence of characters produced for
those specifiers that are described as depending on the C locale are
instead implementation-defined.18)
Returns:
An iterator pointing immediately after the last character produced.
_________________________
16) Although the C programming language defines no modifiers, most
vendors do.
17) Interpretation of the modifier argument is implementation-defined,
but should follow POSIX conventions.
18) Implementations are encouraged to refer to other standards (such
as POSIX) for these definitions.
22.2.5.4 Template class [lib.locale.time.put.byname]
time_put_byname
namespace std {
template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
class time_put_byname : public time_put<charT, OutputIterator>
{
public:
explicit time_put_byname(const char*, size_t refs = 0);
protected:
~time_put_byname(); // virtual
virtual iter_type do_put(iter_type s, ios_base&, char_type, const tm* t,
char format, char modifier) const;
};
}
22.2.6 The monetary category [lib.category.monetary]
1 These templates handle monetary formats. A template parameter indi-
cates whether local or international monetary formats are to be used.
2 All specifications of member functions for money_put and money_get in
the subclauses of _lib.category.monetary_ only apply to the instantia-
tions required in Table 52 and Table 53. Their members use their
ios_base&, ios_base::iostate&, and fill arguments as described in
(_lib.locale.categories_), and the moneypunct<> and ctype<> facets, to
determine formatting details.
22.2.6.1 Template class money_get [lib.locale.money.get]
namespace std {
template <class charT,
class InputIterator = istreambuf_iterator<charT> >
class money_get : public locale::facet {
public:
typedef charT char_type;
typedef InputIterator iter_type;
typedef basic_string<charT> string_type;
explicit money_get(size_t refs = 0);
iter_type get(iter_type s, iter_type end, bool intl,
ios_base& f, ios_base::iostate& err,
long double& units) const;
iter_type get(iter_type s, iter_type end, bool intl,
ios_base& f, ios_base::iostate& err,
string_type& digits) const;
static locale::id id;
protected:
~money_get(); // virtual
virtual iter_type do_get(iter_type, iter_type, bool, ios_base&,
ios_base::iostate& err, long double& units) const;
virtual iter_type do_get(iter_type, iter_type, bool, ios_base&,
ios_base::iostate& err, string_type& digits) const;
};
}
22.2.6.1.1 money_get members [lib.locale.money.get.members]
iter_type get(iter_type s, iter_type end, bool intl,
ios_base& f, ios_base::iostate& err,
long double& quant) const;
iter_type get(s, iter_type end, bool intl, ios_base&f,
ios_base::iostate& err, string_type& quant) const;
Returns:
do_get(s, end, intl, f, err, quant)
22.2.6.1.2 money_get virtual [lib.locale.money.get.virtuals]
functions
iter_type do_get(iter_type s, iter_type end, bool intl,
ios_base& str, ios_base::iostate& err,
long double& units) const;
iter_type do_get(iter_type s, iter_type end, bool intl,
ios_base& str, ios_base::iostate& err,
string_type& digits) const;
Effects:
Reads characters from s to parse and construct a monetary value
according to the format specified by a moneypunct<charT, Intl> facet
reference mp and the character mapping specified by a ctype<charT>
facet reference ct obtained from the locale returned by str.get-
loc(), and str.flags(). If a valid sequence is not recognized, sets
the argument err to (err|str.failbit) and does not change units or
digits; otherwise, it does not change err. Uses the pattern
returned by mp.neg_format() to parse all values. The result is
returned as an integral value stored in units or as a sequence of
digits possibly preceded by a minus sign (as produced by ct.widen(c)
where c is '-' or in the range from '0' through '9', inclusive)
stored in digits. [Example: The sequence $1,056.23 in a common
United States locale would yield, for units, 105623, or, for digits,
"105623". --end example] If mp.grouping() indicates that no thou-
sands separators are permitted, any such characters are not read,
and parsing is terminated at the point where they first appear.
Otherwise, thousands separators are optional; if present, they are
checked for correct placement only after all format components have
been read.
1 Where space or none appears in the format pattern, except at the end,
optional white space (as recognized by ct.is) is consumed after any
required space. If (str.flags() & str.showbase) is false, the cur-
rency symbol is optional and is consumed only if other characters are
needed to complete the format; otherwise, the currency symbol is
required.
2 If the first character (if any) in the string pos returned by mp.posi-
tive_sign() or the string neg returned by mp.negative_sign() is
recognized in the position indicated by sign in the format pattern, it
is consumed and any remaining characters in the string are required
after all the other format components. [Example: If showbase is off,
then for a neg value of "()" and a currency symbol of "L", in "(100
L)" the "L" is consumed; but if neg is "-", the "L" in "-100 L" is not
consumed. ] If pos or neg is empty, the sign component is optional,
and if no sign is detected, the result is given the sign that corre-
sponds to the source of the empty string. Otherwise, the character in
the indicated position must match the first character of pos or net,
and the result is given the corresponding sign. If the first charac-
ter of pos is equal to the first character of neg, or if both strings
are empty, the result is given a positive sign.
3 Digits in the numeric monetary component are extracted and placed in
digits, or into a character buffer buf1 for conversion to produce a
value for units, in the order in which they appear, preceded by a
minus sign if and only if the result is negative. The value units is
produced as if by19)
for (int i = 0; i < n; ++i)
buf2[i] = src[find(atoms, atoms+sizeof(src), buf1[i]) - atoms];
buf2[n] = 0;
sscanf(buf2, "%Lf", &units);
where n is the number of characters placed in buf1, buf2 is a charac-
ter buffer, and the values src and atoms are defined as if by
static const char src[] = "0123456789-";
charT atoms[sizeof(src)];
ct.widen(src, src + sizeof(src) - 1, atoms);
Returns:
An iterator pointing immediately beyond the last character recog-
nized as part of a valid monetary quantity.
+------- BEGIN BOX 7 -------+
Incorporate discussion of error state as per 22-031 - NCM.
+------- END BOX 7 -------+
22.2.6.2 Template class money_put [lib.locale.money.put]
namespace std {
template <class charT,
class OutputIterator = ostreambuf_iterator<charT> >
class money_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
typedef basic_string<charT> string_type;
explicit money_put(size_t refs = 0);
iter_type put(iter_type s, bool intl, ios_base& f,
char_type fill, long double units) const;
iter_type put(iter_type s, bool intl, ios_base& f,
char_type fill, const string_type& digits) const;
static locale::id id;
_________________________
19) The semantics here are different from ct.narrow.
protected:
~money_put(); // virtual
virtual iter_type
do_put(iter_type, bool, ios_base&, char_type fill,
long double units) const;
virtual iter_type
do_put(iter_type, bool, ios_base&, char_type fill,
const string_type& digits) const;
};
}
22.2.6.2.1 money_put members [lib.locale.money.put.members]
iter_type put(iter_type s, bool intl, ios_base& f, char_type fill,
long double quant) const;
iter_type put(iter_type s, bool intl, ios_base& f, char_type fill,
const string_type& quant) const;
Returns:
do_put(s, intl, f, loc, quant)
22.2.6.2.2 money_put virtual [lib.locale.money.put.virtuals]
functions
iter_type do_put(iter_type s, bool intl, ios_base& str,
char_type fill, long double units) const;
iter_type do_put(iter_type s, bool intl, ios_base& str,
char_type fill, const string_type& digits) const;
Effects:
Writes characters to s according to the format specified by a
moneypunct<charT, Intl> facet reference mp and the character mapping
specified by a ctype<charT> facet reference ct obtained from the
locale returned by str.getloc(), and str.flags(). The argument
units is transformed into a sequence of wide characters as if by
ct.widen(buf1, buf1 + sprintf(buf1, "%.01f", units), buf2)
for character buffers buf1 and buf2. If the first character in dig-
its or buf2 is equal to ct.widen('-'), then the pattern used for
formatting is the result of mp.neg_format(); otherwise the pattern
is the result of mp.pos_format(). Digit characters are written,
interspersed with any thousands separators and decimal point speci-
fied by the format, in the order they appear (after the optional
leading minus sign) in digits or buf2. In digits, only the optional
leading minus sign and the immediately subsequent digit characters
(as classified according to ct) are used; any trailing characters
(including digits appearing after a non-digit character) are
ignored. Calls str.width(0).
Notes:
The currency symbol is generated if and only if (str.flags() &
str.showbase) is nonzero. If the number of characters generated for
the specified format is less than the value returned by str.width()
on entry to the function, then copies of fill are inserted as neces-
sary to pad to the specified width. For the value af equal to
(str.flags() & str.adjustfield), if (af == str.internal) is true,
the fill characters are placed where none or space appears in the
formatting pattern; otherwise if (af == str.left) is true, they are
placed after the other characters; otherwise, they are placed before
the other characters. [Note: It is possible, with some combinations
of format patterns and flag values, to produce output that cannot be
parsed using num_get<>::get. --end note]
Returns:
An iterator pointing immediately after the last character produced.
22.2.6.3 Template class moneypunct [lib.locale.moneypunct]
namespace std {
class money_base {
public:
enum part { none, space, symbol, sign, value };
struct pattern { char field[4]; };
};
template <class charT, bool International = false>
class moneypunct : public locale::facet, public money_base {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit moneypunct(size_t refs = 0);
charT decimal_point() const;
charT thousands_sep() const;
string grouping() const;
string_type curr_symbol() const;
string_type positive_sign() const;
string_type negative_sign() const;
int frac_digits() const;
pattern pos_format() const;
pattern neg_format() const;
static locale::id id;
static const bool intl = International;
protected:
~moneypunct(); // virtual
virtual charT do_decimal_point() const;
virtual charT do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_curr_symbol() const;
virtual string_type do_positive_sign() const;
virtual string_type do_negative_sign() const;
virtual int do_frac_digits() const;
virtual pattern do_pos_format() const;
virtual pattern do_neg_format() const;
};
}
The moneypunct<> facet defines monetary formatting parameters used by
money_get<> and money_put<>. A monetary format is a sequence of four
components, specified by a pattern value p, such that the part value
static_cast<part>(p.field[i]) determines the ith component of the
format20) In the field member of a pattern object, each value symbol,
sign, value, and either space or none appears exactly once. The value
none, if present, is not first; the value space, if present, is nei-
ther first nor last.
1 Where none or space appears, white space is permitted in the format,
except where none appears at the end, in which case no white space is
permitted. The value space indicates that at least one space is
required at that position. Where symbol appears, the sequence of
characters returned by curr_symbol() is permitted, and can be
required. Where sign appears, the first (if any) of the sequence of
characters returned by positive_sign() or negative_sign() (respec-
tively as the monetary value is non-negative or negative) is required.
Any remaining characters of the sign sequence are required after all
other format components. Where value appears, the absolute numeric
monetary value is required.
2 The format of the numeric monetary value is a decimal number:
value ::= units [ decimal-point [ digits]] |
decimal-point digits
If frac_digits() returns a positive value, or
value ::= units
otherwise. The symbol decimal-point indicates the character returned
by decimal_point(). The other symbols are defined as follows:
units ::= digits [ thousands-sep units ]
digits ::= adigit [ digits ]
In the syntax specification, the symbol adigit is any of the values
ct.widen(c) for c in the range '0' through '9', inclusive, and ct is a
reference of type const ctype<charT>& obtained as described in the
definitions of money_get<> and money_put<>. The symbol thousands-sep
is the character returned by thousands_sep(). The space character
used is the value ct.widen(' '). White space characters are those
characters c for which ci.is(space, c) returns true. The number of
digits required after the decimal point (if any) is exactly the value
returned by frac_digits().
3 The placement of thousands-separator characters (if any) is determined
by the value returned by grouping(), defined identically as the member
numpunct<>::do_grouping().
22.2.6.3.1 moneypunct members [lib.locale.moneypunct.members]
_________________________
20) An array of char, rather than an array of part, is specified for
pattern::field purely for efficiency.
charT decimal_point() const;
charT thousands_sep() const;
string grouping() const;
string_type curr_symbol() const;
string_type positive_sign() const;
string_type negative_sign() const;
int frac_digits() const;
pattern pos_format() const;
pattern neg_format() const;
1 Each of these functions F returns the result of calling the corre-
sponding virtual member function do_F().
22.2.6.3.2 moneypunct virtual [lib.locale.moneypunct.virtuals]
functions
charT do_decimal_point() const;
Returns:
The radix separator to use in case do_frac_digits() is greater than
zero.21)
charT do_thousands_sep() const;
Returns:
The digit group separator to use in case do_grouping() specifies a
digit grouping pattern.22)
string do_grouping() const;
Returns:
A pattern defined identically as the result of
numpunct<charT>::do_grouping().23)
string_type do_curr_symbol() const;
Returns:
A string to use as the currency identifier symbol.24)
_________________________
21) In common U.S. locales this is '.'.
22) In common U.S. locales this is ','.
23) This is most commonly the value "\003" not "3").
24) For international instantiations (second template parameter true)
this is always four characters long, usually three letters and a
space.
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;25) do_negative_sign() returns the string to use to
indicate a negative value.
int do_frac_digits() const;
Returns:
The number of digits after the decimal radix separator, if any.26)
pattern do_pos_format() const;
pattern do_neg_format() const;
Returns:
The instantiations required in Table 52, namely moneypunct<char>,
moneypunct<wchar_t>, moneypunct<char,true>, and money-
punct<wchar_t,true>, return an object of type pattern initialized to
{ symbol, sign, none, value }.27)
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 string do_grouping() const;
virtual string_type do_curr_symbol() const;
virtual string_type do_positive_sign() const;
virtual string_type do_negative_sign() const;
virtual int do_frac_digits() const;
virtual pattern do_pos_format() const;
virtual pattern do_neg_format() const;
};
}
_________________________
25) This is usually the empty string.
26) In common U.S. locales, this is 2.
27) Note that the international symbol returned by do_curr_sym() usu-
ally contains a space, itself; for example, "USD ".
22.2.7 The message retrieval category [lib.category.messages]
1 Class messages<charT> implements retrieval of strings from message
catalogs.
22.2.7.1 Template class messages [lib.locale.messages]
namespace std {
class messages_base {
public:
typedef int catalog;
};
template <class charT>
class messages : public locale::facet, public messages_base {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit messages(size_t refs = 0);
catalog open(const basic_string<char>& fn, const locale&) const;
string_type get(catalog c, int set, int msgid,
const string_type& dfault) const;
void close(catalog c) const;
static locale::id id;
protected:
~messages(); // virtual
virtual catalog do_open(const basic_string<char>&, const locale&) const;
virtual string_type do_get(catalog, int set, int msgid,
const string_type& dfault) const;
virtual void do_close(catalog) const;
};
}
1 Values of type messages_base::catalog usable as arguments to members
get and close can be obtained only by calling member open.
22.2.7.1.1 messages members [lib.locale.messages.members]
catalog open(const basic_string<char>& name, const locale& loc) const;
Returns:
do_open(name, loc).
string_type get(catalog cat, int set, int msgid,
const string_type& dfault) const;
Returns:
do_get(cat, set, msgid, dfault).
void close(catalog cat) const;
Effects:
Calls do_close(cat).
22.2.7.1.2 messages virtual [lib.locale.messages.virtuals]
functions
catalog do_open(const basic_string<char>& name,
const locale& loc) const;
Returns:
A value that may be passed to get() to retrieve a message, from the
message catalog identified by the string name according to an imple-
mentation-defined mapping. The result can be used until it is
passed to close().
Returns a value less than 0 if no such catalog can be opened.
Notes:
The locale argument loc is used for character set code conversion
when retrieving messages, if needed.
string_type do_get(catalog cat, int set, int msgid,
const string_type& dfault) const;
Requires:
A catalog cat obtained from open() and not yet closed.
Returns:
A message identified by arguments set, msgid, and dfault, according
to an implementation-defined mapping. If no such message can be
found, returns dfault.
void do_close(catalog cat) const;
Requires:
A catalog cat obtained from open() and not yet closed.
Effects:
Releases unspecified resources associated with cat.
Notes:
The limit on such resources, if any, is implementation-defined.
22.2.7.2 Template class [lib.locale.messages.byname]
messages_byname
namespace std {
template <class charT>
class messages_byname : public messages<charT> {
public:
explicit messages_byname(const char*, size_t refs = 0);
protected:
~messages_byname(); // virtual
virtual catalog do_open(const basic_string<char>&, const locale&) const;
virtual string_type do_get(catalog, int set, int msgid,
const string_type& dfault) const;
virtual void do_close(catalog) const;
};
}
22.2.8 Program-defined facets [lib.facets.examples]
1 A C++ program may define facets to be added to a locale and used iden-
tically as the built-in facets. To create a new facet interface, C++
programs simply derive from locale::facet a class containing a static
member: static locale::id id.
2 [Note: The locale member function templates verify its type and stor-
age class. --end note]
3 This initialization/identification system depends only on the initial-
ization to 0 of static objects, before static constructors are called.
When an instance of a facet is installed in a locale, the locale
checks whether an id has been assigned, and if not, assigns one.
Before this occurs, any attempted use of its interface causes the
bad_cast exception to be thrown.
4 [Example: Here is a program that just calls C functions:
#include <locale>
extern "C" void c_function();
int main()
{
using namespace std;
locale::global(locale("")); // same as setlocale(LC_ALL, "");
c_function();
return 0;
}
In other words, C library localization is unaffected. --end example]
5 [Example: Traditional global localization is still easy:
#include <iostream>
#include <locale>
int main(int argc, char** argv)
{
using namespace std;
locale::global(locale("")); // set the global locale
// imbue it on all the std streams
cin.imbue(locale());
cout.imbue(locale());
cerr.imbue(locale());
wcin.imbue(locale());
wcout.imbue(locale());
wcerr.imbue(locale());
return MyObject(argc, argv).doit();
}
--end example]
6 [Example: Greater flexibility is possible:
#include <iostream>
#include <locale>
int main()
{
using namespace std;
cin.imbue(locale("")); // the user's preferred locale
cout.imbue(locale::classic());
double f;
while (cin >> f) cout << f << endl;
return (cin.fail() != 0);
}
In a European locale, with input 3.456,78, output is 3456.78. --end
example]
7 This can be important even for simple programs, which may need to
write a data file in a fixed format, regardless of a user's prefer-
ence.
8 [Example: Here is an example of the use of locales in a library inter-
face.
// file: Date.h
#include <iosfwd>
#include <string>
#include <locale>
...
class Date {
...
public:
Date(unsigned day, unsigned month, unsigned year);
std::string asString(const std::locale& = std::locale());
};
istream& operator>>(istream& s, Date& d);
ostream& operator<<(ostream& s, Date d);
...
This example illustrates two architectural uses of class locale.
9 The first is as a default argument in Date::asString(), where the
default is the global (presumably user-preferred) locale.
10The second is in the operators << and >>, where a locale "hitchhikes"
on another object, in this case a stream, to the point where it is
needed.
// file: Date.C
#include "Date" // includes <ctime>
#include <sstream>
std::string Date::asString(const std::locale& l)
{
using namespace std;
ostringstream s; s.imbue(l);
s << *this; return s.str();
}
std::istream& operator>>(std::istream& s, Date& d)
{
using namespace std;
istream::sentry cerberos(s);
if (cerberos) {
ios_base::iostate err = goodbit;
struct tm t;
use_facet< time_get<char> >(s.getloc()).get_date(s, 0, s, err, &t);
if (!err) d = Date(t.tm_day, t.tm_mon + 1, t.tm_year + 1900);
s.setstate(err);
}
return s;
}
--end example]
11A locale object may be extended with a new facet simply by construct-
ing it with an instance of a class derived from locale::facet. The
only member a C++ program must define is the static member id, which
identifies your class interface as a new facet.
12[Example: Classifying Japanese characters:
// file: <jctype>
#include <locale>
namespace My {
using namespace std;
class JCtype : public locale::facet {
public:
static locale::id id; // required for use as a new locale facet
bool is_kanji(wchar_t c);
JCtype() {}
protected:
~JCtype() {}
};
}
// file: filt.C
#include <iostream>
#include <locale>
#include "jctype" // above
std::locale::id JCtype::id; // the static JCtype member declared above.
int main()
{
using namespace std;
typedef ctype<wchar_t> wctype;
locale loc(locale(""), // the user's preferred locale ...
new My::JCType); // and a new feature ...
wchar_t c = use_facet<wctype>(loc).widen('!');
if (use_facet<My::JCType>(loc).is_kanji(c))
cout << "no it isn't!" << endl;
return 0;
}
13The new facet is used exactly like the built-in facets. --end exam-
ple]
14[Example: Replacing an existing facet is even easier. Here we do not
define a member id because we are reusing the numpunct<charT> facet
interface:
// file: my_bool.C
#include <iostream>
#include <locale>
#include <string>
namespace My {
using namespace std;
typedef numpunct_byname<char> cnumpunct;
class BoolNames : public cnumpunct {
protected:
string do_truename() { return "Oui Oui!"; }
string do_falsename() { return "Mais Non!"; }
~BoolNames() {}
public:
BoolNames(const char* name) : cnumpunct(name) {}
};
}
int main(int argc, char** argv)
{
using namespace std;
// make the user's preferred locale, except for...
locale loc(locale(""), new My::BoolNames(""));
cout.imbue(loc);
cout << boolalpha << "Any arguments today? " << (argc > 1) << endl;
return 0;
}
--end example]
22.3 C Library Locales [lib.c.locales]
1 Header <clocale> (Table 13):
Table 13--Header <clocale> synopsis
+-------------------------------------------------+
| Type Name(s) |
+-------------------------------------------------+
|Macros: |
| LC_ALL LC_COLLATE LC_CTYPE |
| LC_MONETARY LC_NUMERIC LC_TIME |
| NULL |
+-------------------------------------------------+
|Struct: lconv |
+-------------------------------------------------+
|Functions: localeconv setlocale |
+-------------------------------------------------+
2 The contents are the same as the Standard C library header <locale.h>.
SEE ALSO: ISO C clause 7.4.