如何在模板类中拆分模板友元函数的定义?

jok*_*oke 5 c++ templates friend-function

下面的示例编译良好,但我无法弄清楚如何在这种特殊情况下分离运算符 <<() 的声明和定义。

每次我尝试拆分定义时,朋友都会造成麻烦,并且 gcc 抱怨运算符 <<() 定义必须恰好采用一个参数。

#include <iostream>
template <typename T>
class Test {
    public:
        Test(const T& value) : value_(value) {}

        template <typename STREAM>
        friend STREAM& operator<<(STREAM& os, const Test<T>& rhs) {
            os << rhs.value_;
            return os;
        }
    private:
        T value_;
};

int main() {
    std::cout << Test<int>(5) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

Operator<<() 应该有一个自由的第一个参数来处理不同类型的输出流(std::cout、std::wcout 或 boost::asio::ip::tcp::iostream)。第二个参数应该绑定到周围类的专门版本。

Test<int> x;
some_other_class y;

std::cout << x; // works
boost::asio::ip::tcp::iostream << x; // works

std::cout << y; // doesn't work
boost::asio::ip::tcp::iostream << y; // works
Run Code Online (Sandbox Code Playgroud)

除此之外,使用非成员函数并不等同于拆分定义和声明,因为非成员函数无法访问类的私有属性。

Nik*_*sov 4

最简单的可能是让所有这些模板操作符成为朋友:

#include <iostream>
template <typename T>
class Test
{
    public:
        Test(const T& value) : value_(value) {}

        template <typename STREAM, typename U>
        friend STREAM& operator<<(STREAM& os, const Test<U>& rhs);

    private:
        T value_;
};

template <typename STREAM, typename T>
STREAM& operator<<( STREAM& os, const Test<T>& rhs )
{
    os << rhs.value_;
    return os;
}
Run Code Online (Sandbox Code Playgroud)