Apache C++ Standard Library User's Guide

## 25.3 Accessing a Locale's Facets

A locale object is like a container or a map, to be more precise, but it is indexed by type at compile time. The indexing operator, therefore, is not the subscript operator `operator[]()`, but rather the template operator `<>`. Access to the facet objects of a locale object is via two member function templates, `use_facet()` and `has_facet()`:

    template<class Facet> const Facet&  use_facet(const locale&);
    template<class Facet> bool          has_facet(const locale&);

The code below demonstrates how they are used. It is an example of the `ctype` facet's usage; all upper case letters of a string read from the standard input stream are converted to lower case letters and written to the standard output stream.

    std::string in;
    std::cin >> in;
    if (std::has_facet< ctype<char> >(std::locale()))     //1
    {
      std::cout << use_facet<ctype<char> >(std::locale()) //2
                   .tolower(in.begin(),in.end());         //3
    }

`//1` | In the call to `has_facet<...>()`, the template argument chooses a base facet class. If no facet of this type is present in a locale object, `has_facet` returns `false`.
`//2` | The function template `use_facet<...>()` returns a reference to the locale's facet object of the specified base facet type. As locale objects are immutable, the reference stays valid throughout the lifetime of the locale object. If no facet of the specified type is present in the locale, `use_facet` throws a `runtime_error` exception.
`//3` | The facet object's member function `tolower()` is called. It has the functionality of the C function `tolower()`; it converts all upper case letters in the string into lower case letters.

In this example, the call to `has_facet` is actually unnecessary because `ctype<char>` is a standard facet. Every locale always contains a complete complement of the standard facets, so `has_facet<ctype<char> >` always returns `true`. However, a call to `has_facet()` can be useful when you are dealing with nonstandard facets, such as the `mythical` facet described earlier in this chapter, which may not be present in every locale.

When you are coding `use_facet` and `has_facet` calls, it is important that the facet type you specify as the template parameter is a base facet type, and not a derived facet type. The following is an error:

    locale loc;
    const std::numpunct_byname<char>& np =         // Error, use_facet
      use_facet<std::numpunct_byname<char> >(loc); // instantiated on
                                                   // a non-base facet
                                                   // type

Depending on the facet type, and on your compiler, this will probably cause a compile-time error. If it does not, it may result in unpredictable runtime behavior. The `use_facet` call returns the facet that occupies the slot for the type `std::numpunct_byname<char>`. But in fact, as described earlier, this is the same as the slot for the base facet type, `std::numpunct<char>`. So the above code may cause `np` to be initialized to a reference to an object that is not, in fact, of type `std::numpunct_byname<char>`.

To avoid errors like this, make sure that you only instantiate `use_facet` and `has_facet` on base facet types, that is, on facet types that contain a static `locale::id` member.

    locale loc;
    const numpunct<char>& np =                      // Correct
          use_facet<numpunct<char> >(loc);