namespace std {
class locale {
public:
class facet;
class id;
using category = int;
static const category
none = 0,
collate = 0x010, ctype = 0x020,
monetary = 0x040, numeric = 0x080,
time = 0x100, messages = 0x200,
all = collate | ctype | monetary | numeric | time | messages;
locale() noexcept;
locale(const locale& other) noexcept;
explicit locale(const char* std_name);
explicit locale(const string& std_name);
locale(const locale& other, const char* std_name, category);
locale(const locale& other, const string& std_name, category);
template<class Facet> locale(const locale& other, Facet* f);
locale(const locale& other, const locale& one, category);
~locale();
const locale& operator=(const locale& other) noexcept;
template<class Facet> locale combine(const locale& other) const;
string name() 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;
static locale global(const locale&);
static const locale& classic();
};
}
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
.Access to the facets of a
locale
is via two function templates,
use_facet<>
and
has_facet<>.[
Example 1:
An iostream operator<< might be implemented as:
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) {
tm tmbuf; d.extract(tmbuf);
bool failed =
use_facet<time_put<charT, ostreambuf_iterator<charT, traits>>>(
s.getloc()).put(s, s, s.fill(), &tmbuf, 'x').failed();
if (failed)
s.setstate(s.badbit);
}
return s;
}
—
end example]
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,
it throws the standard exception
bad_cast. A C++ program can check if a locale implements a particular
facet with the
function template
has_facet<Facet>(). User-defined facets may be installed in a locale, and used identically as
may standard facets
.[
Note 1:
All locale semantics are accessed via
use_facet<>
and
has_facet<>,
except that:
- A member operator template
operator()(const basic_string<C, T, A>&, const basic_string<C, T, A>&)
is provided so that a locale can 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).
—
end note]
Once a facet reference is obtained from a locale object by calling
use_facet<>,
that reference remains usable, and the results from member functions
of it may be cached and re-used, as long as some locale object refers
to that facet
.In successive calls to a locale facet member function on a facet object
installed in the same locale, the returned result shall be identical
.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
"*".Whether there is one global locale object for the entire program or one global locale
object per thread is
implementation-defined
. Implementations should provide one global locale object per
thread
. If there is a single global locale object for the entire program,
implementations are not required to
avoid data races on it
.