Apache C++ Standard Library User's Guide

## 25.1 Understanding Facet Types

A facet is an object which can be stored in a locale and retrieved from the locale based on its type. Facets encapsulate data about cultural and language dependencies. They also contain services (functions) that use the encapsulated data to help you internationalize your programs.

The C++ Standard Library defines a number of facet classes, which we call standard facets. These facets were reviewed in the previous chapter; they are present in every locale. You can derive your own facet classes from the standard facets, to modify their behavior. You can also create entirely new facet classes, to handle aspects of internationalization that the standard facets don't cover. Both of these processes are described later in this chapter.

In talking about facet classes, we need to distinguish between base facets and derived facets. A base facet is a class with the following properties:

- It is derived from class `std::locale::facet`.

- It contains a static data member named `id`, of type `std::locale::id`.

These properties make it possible to store the facet in a locale, and to retrieve it from the locale based on its type. A locale contains at most one facet of each base facet type.

A derived facet is a class that is derived from a base facet, but does not contain its own static `std::locale::id` member. Instead, it inherits this member from the base facet it derives from. Like any facet, a derived facet can be stored in a locale, but it occupies the same slot in the locale as its base facet, displacing any other facet that was in that slot. For example, the following skeletal code defines a mythical base facet and a facet derived from it, and shows some of the ways these mythical facets can be stored in and retrieved from locales:

    class mythical: public std::locale::facet {                  //1
      public:
       static std::locale::id id;
       ... // etc
    };

    std::locale::id mythical::id;

    class mythical_byname: public mythical {                     //2
      public:
        mythical_byname (char *name,/*etc*/); // Constructor
        ... // etc
    };

    int main (void) {
      std::locale loc0(std::locale::classic());                  //3
      std::locale loc1(loc0,new mythical);                       //4
      std::locale loc2(loc1,new mythical_byname("he_DO"));       //5
      const mythical& m2=std::use_facet<mythical>(loc2);         //6
      const mythical& m1=std::use_facet<mythical>(loc1);         //7
      const mythical& m0=std::use_facet<mythical>(loc0);         //8
    }

`//1` | An example of a base facet class, derived from`std::locale::facet` and containing a static `std::locale::id` member name `id`.
`//2` | A derived facet class.
`//3` | A copy of the classic locale. Like all locales, it contains many facets. The facets are kept in slots indexed by the set of possible base facet types. Thus there is one slot for the base facet type `mythical`. In the classic locale, this `mythical` slot is empty.
`//4` | A copy of `loc0`, the classic locale, with its `mythical` slot now occupied by a newly-created `mythical` facet.
`//5` | A copy of `loc1`, but with the `mythical` slot now occupied by a newly-created `mythical_byname` facet.

`//6`

This returns a reference to the `mythical_byname` facet constructed in `//5`. However, note that you no longer know that it is a `mythical_byname` facet (short of using RTTI, which is cheating in this context). All you know is that it is a `mythical` facet, because it came from the `mythical` slot in the locale. (The `std::use_facet` function template is described in more detail later in this chapter.)

`//7` | This returns a reference to the `mythical` facet constructed in step `//4`.
`//8` | This causes a `std::bad_cast` exception to be thrown, because the `mythical` slot in `loc0` is empty.

The standard facets that come with the library are all defined as class templates. The first template parameter is always the character type the facet will operate on, which is usually `char` or `wchar_t`. Some of the facets have additional template parameters. As another example of the distinction between base facets and derived facets, here is a stripped-down version of the Standard facet template `std::numpunct`, which takes a single template parameter.

    template <class charT>
    class numpunct: public std::locale::facet {
      public:
        static std::locale::id id;
        ... // etc
    };

    template <class charT>
    class numpunct_byname: public numpunct<charT> {
      ... // etc
    };

Typically, these templates are instantiated on `char` and `wchar_t`, so the following are base facet types:

    std::numpunct<char>
    std::numpunct<wchar_t>

and the following are derived facet types:

    std::numpunct_byname<char>
    std::numpunct_byname<wchar_t>

If your application created its own character type `my_char_t`, then `std::numpunct<my_char_t>` would be a base facet type and `std::numpunct_byname<my_char_t>` would be a derived facet type.