It is amazing how much code you can cram into a single line, and how much magic happens behind the scenes when you do. I’m working on a pet project in one of the fields I like most: embeddable domain-specific languages. One of the things I want to be able to do with this particular domain-specific language is output any type of literal for debugging purposes while compiling (or interpreting) the script. In order to do that, I want my code to be expressive such that typing

C c(...);
cout << c << endl;

will “just work”. To accomplish that, I’ve written a little class that’s called “Serializable” that looks like this:

template < typename T >
struct Serializable 
{
    template < typename Y > friend Y& operator<<(Y &out;, const T & t) { t.serialize(out); return out; }
};

To make a type serializable with this, all you need to dos derive from Serializable and implement serialize, like so:

struct Complex : Serializable< Complex >
{
    double real_;
    double imag_;

    template < typename S >
    void serialize(S &s;)
    {
        s << '(' << real_ << ',' << imag_ << ')';
    }
};

This trick is called the Barton-Nackman idiom, and generates an operator that would look like this:

template < typename S >
S& operator<<(S &s;, const Complex &c;)
{
    c.serialize(s);
    return s;
}

Note that in this case only S is still a template parameter: T has become the type Complex, which is what we wanted. Also note that the new operator is not a member: it’s a stand-alone operator that is an overload of the usual operator<<. That’s what the friend declaration is for: omitting friend in this case would have made the operator a member – and would not have worked as expected.