友元函数上的模板链接器错误

And*_*cco 0 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;
}
Run Code Online (Sandbox Code Playgroud)

该代码片段应该在编译期间产生错误,而且确实如此。这是链接器错误,但我无法理解。

我尝试更改几行代码,错误似乎是由模板的安装引起的operator<<,因为删除该模板并编写特定的运算符使代码可以工作。我还感觉模板会被实例化多次,而不仅仅是int.

然而,据我有限的知识,模板定义似乎很好。我缺少什么?

确切的错误(VS 2017)是: Error LNK2019: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,class A const &)" (??6@YAAEAV?$ basic_ostream@DU?$char_traits@D@std@@@std@@AEAV01@AEBV?$A@H@@@Z) 在 main 函数中引用

iBu*_*Bug 6

您需要将友元函数声明为模板:

class A {
   ...
   template <class U>  // <-- NOTICE ---------------v
   friend ostream & operator<<(ostream & c, const A<U> & v);
   ...
Run Code Online (Sandbox Code Playgroud)

或者更好的是,使用更安全的方法,尽管有点冗长:

#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;
}
Run Code Online (Sandbox Code Playgroud)

请参阅此页面了解更多详细信息。