朋友功能上的模板链接器错误

时间:2019-02-03 08:38:34

标签: c++ templates

在学习模板时,我遇到了以下练习:

#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

1 个答案:

答案 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