如何在模板类中拆分模板友元函数的定义?
下面的示例编译良好,但我无法弄清楚如何在这种特殊情况下分离运算符<<() 的声明和定义。
每次我尝试拆分定义时,朋友都会造成麻烦,并且 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;
}
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
除此之外,使用非成员函数并不等同于拆分定义和声明,因为非成员函数无法访问类的私有属性。
The following example compiles fine but I can't figure out how to separate declaration and definition of operator<<() is this particular case.
Every time I try to split the definition friend is causing trouble and gcc complains the operator<<() definition must take exactly one argument.
#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;
}
Operator<<() is supposed to have a free first parameter to work with different kind of output streams (std::cout, std::wcout or boost::asio::ip::tcp::iostream). The second parameter should be bound to a specialized version of the surrounding class.
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
Besides that using a non-member-function isn't equivalent to splitting the definition and declaration because non-member-functions can't access private attributes the the class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
最简单的可能是让所有这些模板操作符成为朋友:
The easiest is probably to make all these template operators friends:
我能实现的最接近的是
声明所有运算符<<作为朋友,而不仅仅是由 T 参数化的朋友。问题是不可能部分专门化函数。有人会喜欢使用,
但这不是有效的语法。 (好吧,部分专业化不能声明为朋友)
The nearest I can achieve is
which declares all operator<< as friend instead of only the one parametrized by T. The problem is that it isn't possible to partially specialize functions. One would have liked to use
but that isn't valid syntax. (Well, and partial specialization can't declared friend)
它不应该在类之外定义吗?
Shouldn't it be defined outside of the class ?
问题在于,在您提供的代码中,友元是仅在第一个参数类型上参数化的模板化函数。也就是说,对于类模板的每个实例化类型 T(称为
mytype
),您都在声明一个自由模板函数:重要的一点是
Test
是带有类型参数mytype
的Test
的特定实例。如果您确实想声明一个在流类型和
Test
模板的实例化类型中模板化的友元函数,则必须声明带有两个参数的友元。另一方面,我建议您不要在流类型上参数化
operator<<
,同时在类大括号内定义它,因为它具有轻微的优势(名称查找规则略有不同)。The problem is that in the code that you present the friend is a templated function parametrized only on the first argument type. That is, for each instantiating type T of the class template (call it
mytype
), you are declaring a free template function:The important point there is that
Test<mytype>
is the particular instantiation ofTest
with type argumentmytype
.If you really want to declare a friend function that is templated in both the stream type and the instantiating type of the
Test
template, you must declare a friend with two arguments.On the other hand, I recommend that you do not parametrize
operator<<
on the stream type, and at the same time, that you define it inside the class braces as it has slight advantages (name lookup rules are slightly different).对于 Test 类的每个实例化类型 T,都会公开一个模板函数运算符<<(),它可以在不同类型的流上进行操作。 operator<<()函数具有自由的第一参数但固定的第二参数。
示例:
这就是测试类应该工作的方式。
For each instantiated type T of class Test a template function operator<<() is exposed which can operate on different kind of streams. The operator<<() function has a free first parameter but a fixed second parameter.
example:
That's the way the Test class was supposed to work.