'Modern pattern to write custom ostream operator

Typically, in C++, we used to define a custom ostream operator<< this way:

class A {
    int impl_;
    friend std::ostream& operator<<(std::ostream& os, A const& self){
       return os << "A:" << self.impl_;
    }
};

However now, post C++11, there are r-value references, and as a matter of fact, built-in types can be streamed to r-value std::ostream references. Now this is allowed:

int i = 5;
std::ofstream("file") << i;

(I don't know if this is the reason the special overloads were defined.)

Does it mean that for consistency one should define both operators for custom classes? Like this,

class A {
    int impl_;
    friend std::ostream& operator<<(std::ostream& os, A const& self) {
       return os << "A:" << self.impl_;
    }
    friend std::ostream&& operator<<(std::ostream&& os, A const& self) {
       os << "A:" << self.impl_; 
       return std::move(os);
    }
};

or more streamlined,

class A {
    int impl_;
    friend std::ostream& operator<<(std::ostream& os, A const& self) {
       return os << "A:" << self.impl_;
    }
    friend std::ostream&& operator<<(std::ostream&& os, A const& self) {
       return std::move(os << self); // calls the other overload
    }
};

What is the recommended way to overload operator<< nowadays in C++11?



Solution 1:[1]

Besides the conceptual discussion, from a technical viewpoint:

After some experimentation I realized that I don't need to overload for the r-value ostream, the library does it for me already.

One only has to have the l-value version and the library has some r-value version that is forwarded to the implemented overload, which presumably works for any std namespace argument of operator << through ADL or something.

So, in C++11, this is allowed std::ofstream{"file"} << a, even if no r-value overload (for the stream) is custom defined.

Which seems to make operator<< quite special in STL.

Corrections are welcome.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1