Name

locale::facet class — Base class for locale facets

Synopsis

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

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);
}