编写自定义 ostream 运算符的现代模式

Modern pattern to write custom ostream operator

通常,在 C++ 中,我们过去常常这样定义自定义 ostream operator<<

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

但是现在,post C++11,有右值引用,事实上,内置类型可以流式传输到右值std::ostream引用。 现在允许:

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

(我不知道这是否是定义特殊重载的原因。)

这是否意味着为了保持一致性,应该为自定义 类 定义两个运算符?像这样,

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);
    }
};

或更精简,

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
    }
};

如今在 C++11 中重载 operator<< 的推荐方法是什么?

除了概念上的讨论,从技术角度来看:

经过一些实验,我意识到我不需要为 r-value ostream 重载,库已经为我完成了。

只需要 l-value 版本并且库有一些 r-value 版本被转发到实现的重载,这大概适用于 operator << 通过 ADL 的任何 std 命名空间参数什么的。

因此,在 C++11 中,这是允许的 std::ofstream{"file"} << a,即使没有 r-value 重载(对于流)是自定义定义的。

这似乎使 operator<< 在 STL 中很特别。

欢迎指正。