Apache C++ Standard Library User's Guide

## 25.4 Using a Stream's Facet

Here is a more advanced example that uses a `std::time_put` facet to print a date. Let us assume we have a date and want to print it this way:

    struct std::tm aDate;                                       //1

    std::memset(aDate,0,sizeof aDate);                          //2
    aDate.tm_year = 1989;
    aDate.tm_mon = 9;
    aDate.tm_mday = 1;

    std::cout.imbue(std::locale("De_CH"));                      //3
    std::cout << aDate;                                         //4

`//1` | A date object is created. It is of type `std::tm`, which is the time structure defined in `<ctime>`.
`//2` | The date object is initialized with a particular date, September 1, 1989.
`//3` | Let's assume our program is supposed to run in a German-speaking canton of Switzerland. Hence, we imbue the standard output stream with a German-Swiss locale.
`//4` | The date is printed in German to the standard output stream.

The output is: `1. September 1989`

As there is no `operator<<()` defined in the C++ Standard Library for the time structure `tm` from the C library, we must provide this inserter ourselves. The following code suggests a way this can be done. If you are not familiar with iostreams, please refer to the iostreams part of this User's Guide.

To keep it simple, the handling of exceptions thrown during the formatting is omitted.

    template<class charT, class traits>
    std::basic_ostream<charT, traits>&
    operator<<(std::basic_ostream<charT,traits>& os,
               const std::tm& date)                            //1
    {
      std::locale loc = os.getloc();                           //2
      typedef std::ostreambuf_iterator<charT,traits>
              outIter_t;                                       //3
      const std::time_put<charT,outIter_t>& fac                //4
          = std::use_facet<std::time_put<charT,
                                         outIter_t> >(loc);    //5
      fac.put(os,os,os.fill(),&date,'x');                      //6
      return os;
    }

`//1` | This is a typical signature of a stream inserter; it takes a reference to an output stream and a constant reference to the object to be printed, and returns a reference to the same stream.
`//2` | The stream's locale object is obtained via the stream's member function `getloc()`. This is the locale object where we expect to find a time-formatting facet object.

`//3`

We define a type for an output iterator to a stream buffer. Time-formatting facet objects write the formatted output via an iterator into an output container (see the sections on containers and iterators in the C++ Standard Library User's Guide). In principle, this can be an arbitrary container that has an output iterator, such as a string or a C++ array. Here we want the time-formatting facet object to bypass the stream's formatting layer and write directly to the output stream's underlying stream buffer. Therefore, the output container shall be a stream buffer.

`//4`

We define a variable that will hold a reference to the locale object's `std::time_put` facet object. The time formatting facet class `std::time_put` has two template parameters:

- The first template parameter is the character type used for output. Here we provide the stream's character type as the template argument.

- The second template parameter is the output iterator type. Here we provide the stream buffer iterator type `outIter_t` that we had defined as before.

`//5` | Here we get the time-formatting facet object from the stream's locale via `std::use_facet()`.

`//6`

The facet object's formatting service `put()` is called. Let us see what arguments it takes. Here is the function's interface:

`iter_type put` | `(iter_type` | `(a)`
| `,ios_base&` | `(b)`
| `,char_type` | `(c)`
| `,const tm*` | `(d)`
| `,char)` | `(e)`

The types `iter_type` and `char_type` stand for the types that were provided as template arguments when the facet class was instantiated. In this case, they are std::ostreambuf_iterator<> and `charT`, where `charT` and `traits` are the respective streams template arguments. Here is the actual call: `nextpos = fac.put(os,os,os.fill(),&date,'x');` Now let's see what the arguments mean:

a. | The first parameter is supposed to be an output iterator. We provide an iterator to the stream's underlying stream buffer. The reference `os` to the output stream is converted to an output iterator, because output stream buffer iterators have a constructor taking an output stream, that is, basic_ostream<>&.
b. | The second parameter is of type ios_base `&`, which is one of the stream base classes. The class ios_base contains data for format control (see the section on iostreams for details). The facet object uses this formatting information. We provide the output stream's ios_base part here, using the automatic cast from a reference to an output stream, to a reference to its base class.
c. | The third parameter is the fill character. It is used when the output has to be adjusted and blank characters have to be filled in. We provide the stream's fill character, which one can get by calling the stream's `fill()` function.
d. | The fourth parameter is a pointer to a time structure `std::tm` defined in `<ctime>`.
e. | The fifth parameter is a format character as in the C function `std::strftime()`; the `x` stands for the locale's appropriate date representation.

The value returned is an output iterator that points to the position immediately after the last inserted character.