28 Localization library [localization]

28.3 Locales [locales]

28.3.1 Class locale [locale] General [locale.general]

namespace std { class locale { public: // types class facet; class id; using category = int; 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() 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(); // not virtual const locale& operator=(const locale& other) noexcept; template<class Facet> locale combine(const locale& other) const; // locale operations 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; // global locale objects 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<< can be implemented as:253 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); // can throw } 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).
    (This eases upgrading existing extractors ([istream.formatted]).)
— 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 ([res.on.data.races]).
Note that in the call to put, the stream is implicitly converted to an ostreambuf_­iterator<charT, traits>.