friend template function
一个带有友元函数的类模板声明(想一想为啥它会出错)如下:
template <typename T>
class Foo {
friend std::ostream& operator<< (std::ostream& os, const Foo<T>& a);
};
operator<<()
被声明为非模板友元函数,对于每一个Foo类使用的类型T,都必须有一个对应的非模板函数operator<<()
,例如,声明一个Foo<int>
类,则必须有如下函数定义
//T=int时,函数定义
std::ostream& operator<< (std::ostream& os, const Foo<int>& a)
{
/*...*/
}
但是由于模板类Foo中的T可以是任何类型,你不可能针对T代表的每个类型都去定义相应的operator<<()
函数,
所以, 导致链接器错误。
为解决这个问题,可在Foo模板类声明之前,将友元函数operator<<()
声明成模板函数
提示为啥这样操作:
模板类的成员函数都是模板函数,但模板类的友元函数可不是模板函数,除非你先将某 函数声明为模板函数,然后将其声明为模板类的友元函数
如下:
// 前置声明Foo
template
<typename> class Foo;
// 前置声明模板函数 operator <<()
template <typename T>
std::ostream& operator<<(std::ostream&, const Foo<T>&);
//Foo模板类的声明
template <typename T>
class Foo {
//将上面的模板函数operator<<()声明为friend
friend std::ostream& operator<< <>(std::ostream& os, const Foo<T>& a);
// 注意不要忘了这里加上了 <>
// ...
};
//模板函数operator<<()的定义
template <typename T>
std::ostream& operator<<(std::ostream& os, const Foo<T>& a) {
// ... implement the operator
}
上面的友元模板函数的方式限制operator<<(std::ostream& os, const Foo<T>& a)
只能访问对应的Foo(T)
,比如operator<< <int>
只能访问Foo <int>
的实例的成员,而不能访问Foo <double>
的实例的成员。
为了让友元模板函数operator<<()
能访问Foo<T>
的所有实例,可进行如下声明
template <typename T>
class Foo {
template <typename T1>
friend std::ostream& operator<<(std::ostream& os, const Foo<T1>& a);
// ...
};
或者是将friend operator<<()
的函数实现直接内嵌在模板类Foo<T>
的定义中,如下:
template <typename T>
class Foo {
//直接内嵌friend operator<<()
friend std::ostream&operator<<(std::ostream& os, const Foo& a)
{
/*...*/
}
// ...
};