Apache C++ Standard Library User's Guide

## 32.3 A Simple Extractor and Inserter for the Example

Following the read and write conventions of iostreams, we would insert and extract the date object like this:

    date birthday(2,6,1952);
    std::cout << birthday << '\n';

or

    date aDate;

    std::cout << '\n' << "Please, enter a date (day month year)"
              << '\n';
    std::cin  >> aDate;
    std::cout << aDate << '\n';

For the next step, we would implement shift operators as inserters and extractors for `date` objects. Here is an extractor for class `date`:

    template<class charT, class Traits>
    std::basic_istream<charT, Traits>&                            //1
    operator>> (std::basic_istream<charT,Traits>& is,             //2
                date& dat)                                        //3
    {
      is >> dat.tm_date.tm_mday;                                  //4
      is >> dat.tm_date.tm_mon;
      is >> dat.tm_date.tm_year;
      return is;                                                  //5
    }

`//1` | The returned value for extractors (and inserters) is a reference to the stream, so that several extractions can be done in one expression.
`//2` | The first parameter usually is the stream from which the data shall be extracted.
`//3` | The second parameter is a reference, or alternatively a pointer, to an object of the user-defined type.
`//4` | In order to allow access to private data of the date class, the extractor must be declared as a friend function in class `date`.
`//5` | The return value is the stream from which the data was extracted.

As the extractor accesses private data members of class date, it must be declared as a friend function to class date. The same holds for the inserter. Here's a more complete version of class `date`:

    class date {
    public:
      date(int d, int m, int y);
      date(tm t);
      date();
      // more constructors and useful member functions

    private:
      std::tm tm_date;

      template<class charT, Traits>
      friend std::basic_istream<charT, Traits>
      &operator >>(std::basic_istream<charT, Traits >& is, date& dat);

      template<class charT, Traits>
      friend std::basic_ostream<charT, Traits>
      &operator <<(std::basic_ostream<charT, Traits >& os,
                   const date& dat);
    };

The inserter can be built analogously, as shown below. The only difference is that you would hand over a constant reference to a date object, because the inserter is not supposed to modify the object it prints.

    template<class charT, class Traits>
    std::basic_ostream<charT, Traits>&
    operator << (std::basic_ostream<charT, Traits >& os,
                 const date& dat)
    {
      os << dat.tm_date.tm_mon << '-';
      os << dat.tm_date.tm_mday << '-';
      os << dat.tm_date.tm_year ;
      return os;
    }