locale::facet class — Base class for locale facets
class locale::facet{ protected: explicit facet(size_t refs = 0); virtual ~facet( ); private: facet(const facet&); // Not defined void operator=(const facet&); // Not defined };
The facet
class is the base
class for all facets. A derived class must also declare a public,
static data member of type locale::id
whose name is id
. Even a derived class must declare its
own id
member because it must
have an identifier that is distinct from that of the base-class
facet. Any other members for a custom facet are entirely up to the
programmer; the derived class does not need to provide a copy or
default constructor or an assignment operator.
The locale
class assigns a
value to id
when the facet object
is added to a locale. You never need to examine or alter the
id
member; it is managed entirely
by locale
.
The explicit constructor for facet
takes a single argument, ref
. If ref
==
0
, the facet
object is not deleted until the last
locale that uses the facet is destroyed. If ref
==
1
, the facet
object is never destroyed. The
standard facet classes (ctype
,
etc.) also take a ref
parameter
and pass it directly to the inherited facet
constructor. Custom facets can do
whatever the programmer wants, such as relying on the default value
of 0
to manage the facet's
lifetime automatically.
For example, suppose you want to define a facet that captures
the locale-specific preferences for units of measure, such as length
and weight. A program can store and manipulate values in a common
base unit and convert to the preferred unit for output. Example 13-26 shows a units
facet that allows you to do these
things.
Example 13-26. A simple facet for working with units of measure
class units : public std::locale::facet { public: enum length_units { length_base=1, mm=10, cm=10*mm, m=10*cm, km=1000*m, in=254, ft=12*in, yd=3*ft, mi=5280*ft }; typedef double value_t; // All facets must have a static ID member. static std::locale::id id; // Constructor initializes length_units_ according to local preferences. units( ); // Read a length and its units, and return the length in base units. value_t length_get(std::istream& stream) const; // Convert value to the preferred units, and print the converted value followed // by the unit name. void length_put(std::ostream& stream, value_t value) const; // Make a base unit value from a value in src_units. value_t make(value_t src_value, length_units src_units) const; // Convert base units to dst_unit. value_t convert(value_t src_value, length_units dst_units) const; // Return the name of a unit. const char* unit_name(length_units units) const; // Return the preferred unit for length. length_units get_length_unit( ) const; private: length_units length_units_; }; int main( ) { // Add the units facet to the global locale: // 1. Construct a new locale that is a copy of the global locale, with the new // units facet added to it. // 2. Set the new locale as the global locale. std::locale loc(std::locale(std::locale( ), new units)); std::locale::global(loc); // Now anyone can get the units facet from the global locale. const units& u = std::use_facet<units>(std::locale( )); units::value_t size = u.make(42, units::cm); u.length_put(std::cout, size); }