在学习模板时,我遇到了以下练习:
#include <iostream>
using namespace std;
template <class T>
class A {
T _v;
public:
A() {}
A(T v) : _v(v) {}
friend ostream & operator<<(ostream & c, const A<T> & v);
};
template <class T>
ostream & operator<<(ostream & c, const A<T> & v){
c << v._v; return c;
}
int main()
{
A<int>a(10);
cout << a << endl;
return 0;
}
此代码段应在编译过程中产生错误,实际上确实如此。这是一个链接器错误,但我听不懂。
我试图更改几行代码,并且错误似乎是由于模板operator<<
的插入引起的,因为删除该模板并编写特定的运算符可使代码正常工作。我还觉得模板不仅被int
实例化了多次,而且还被实例化了。
但是,据我所知,模板定义似乎还不错。我想念什么?
确切的错误(VS 2017)是: 错误LNK2019:无法解析的外部符号“ class std :: basic_ostream>&__cdecl运算符<<(class std :: basic_ostream>&,class A const&)”(?? 6 @ YAAEAV?$ basic_ostream @ DU?$ char_traits @ D @函数main中引用的std @@@ std @@ AEAV01 @ AEBV?$ A @ H @@@@ Z
答案 0 :(得分:2)
您需要声明朋友功能作为模板:
class A {
...
template <class U> // <-- NOTICE ---------------v
friend ostream & operator<<(ostream & c, const A<U> & v);
...
或者更好,尽管更冗长一些,但使用更安全的方法:
#include <iostream>
using namespace std;
template <class T>
class A;
template <class T>
ostream& operator<<(ostream& c, const A<T>& v);
template <class T>
class A {
T _v;
public:
A() {}
A(T v) : _v(v) {}
friend ostream& operator<< <T>(ostream& c, const A<T>& v);
};
template <class T>
ostream& operator<<(ostream& c, const A<T>& v) {
c << v._v;
return c;
}
int main() {
A<int> a(10);
cout << a << endl;
return 0;
}
有关更多详细信息,请参见this page。