0

I've encountered the following exercises while studying 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;
}

This code snippet should produce an error during compilation and it actually does. It's a linker error, but I can't understand it.

I tried to change a few lines of code and the error seems to be caused by the instation of the template operator<<, since removing that template and writing a specific operator make the code work. I also have the feeling that the template gets instantiated multiple times, not only for int.

However, to my limited knowledge, the template definition seems fine. What am I missing?

The exact error (VS 2017) is: 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) referenced in function main

Andrea Bocco
  • 792
  • 5
  • 14

1 Answers1

4

You need to declare the friend function as template:

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

Or better yet, use a safer approach, despite a bit more verbose:

#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;
}

See this page for more details.

iBug
  • 35,554
  • 7
  • 89
  • 134