0%

C++中模板类的输出流重载

概述

在模板类中使用输出流重载发现报错,g++提示

warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const A&)’ declares a non-template function
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
增加<>后依旧报错,遂百度之,解决。

原因

定义的友元函数还是一个模版,要实例化为参数变元后才能使用。也就是说,即使上面的友元看起来像函数定义,但是若没有经过参数化,编译器就不会生成该函数的代码
关于操作符的友元模版函数重载
个人理解是由于友元函数还没有给出声明(或者说是定义),编译器识别不出来。所以可以在类之前预先声明,而又因为该函数使用了类名,所以类名也要预先声明。

解决方法

1.在类内部加上友元函数体(不推荐)

2.在类的定义之前对类和友元函数进行预声明,并在内部加上<>

即在类定义前加上如下代码:

1
2
template <typename T> class A;
template <typename T> ostream &operator<< (ostream &out, const A<T> &a);

在类定义中给输出流重载函数加上<>:

1
2
public:
friend ostream &operator<< <>(ostream &, const A<T> &);

注意:重载函数定义时不需要加上<>

与其他友元函数定义类似:

1
2
3
4
5
6
7
8
9
10
template <typename T>
ostream &operator<< (ostream &out, const A<T> &a)
{
for (int i = 0; i < a.length; i++)
{
out << a[i] << " ";
}
return out;
}

3.在类中再使用一次模板(自用)

参考关于操作符的友元模版函数重载
直接修改类定义中的输出流重载函数为:

1
2
3
public:
template <typename T1>
friend ostream &operator<<(ostream &, const A<T1> &);

重载函数定义不需要修改为T1(当然改也行)

参考

C++ 模板类友元之输出流操作符重载
关于操作符的友元模版函数重载