LNK2019 linker error

Hi,

I am porting an application from gcc to Visual Studio 2005 and I found a lot of problems.

I read in amsdn sitethis solution for the LNK2019 error that is similar to my problem but it simply doesn't work.

// LNK2019e.cpp
// compile with: /EHsc
// LNK2019 expected
#include <iostream>
usingnamespace std;

template<class T>class
Test{
friend ostream&operator<<(ostream&, Test&);
// Uncomment the following line to resolve.
// template<typename T> friend ostream& operator << (ostream&, Test<T>&);
};

template<typename T>
ostream&operator<<(ostream& os, Test<T>& tt){
return os;
}

int main(){
Test<int> t;
cout<<"Test: "<< t<< endl;// unresolved external
}
The description of the error is:

Error 1 error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Test<int> &)" (?6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAV?$Test@H@@@Z) referenced in function _main main.obj

Error 2 fatal error LNK1120: 1 unresolved externals C:\Documents and Settings\tiago\Os meus documentos\Visual Studio 2005\Projects\testGenPoint\Debug\testGenPoint.exe

Is there any option in VS to solve the problem?

thanks

[3239 byte] By [great_ghost] at [2007-12-17]
# 1

There is a bug in your code. The line:

friend ostream& operator<<(ostream&, Test&);

Tells the compiler that the global function "ostream& operator<<(ostream&, Test&)" is a friend of the current class. Note: I said global function: not specialization of a function template that might just happen to have this signature.

So even though you provide a function template that could be specialized to a have the same signature as this function the C++ language specifically disallows a compiler from choosing this function: mostly because the signature actually don't match.

The signature of the friend function is:

ostream& operator<<(ostream&, Test<int>&);

but the specialization of the function template is:

ostream& operator<<<int>(ostream&, Test<int>&);

Hmm this is getting confusing ... let's make this a bit easier and assume your friend function and the function template are both named 'f' instead of 'operator<<'

The signature of the friend function is:

ostream& f(ostream&, Test<int>&);

the signature of the specialization of the function template is:

ostream& f<int>(ostream&, Test<int>&);

These are different functions: C++ allows the following:

template<typename T>
void f(T);

void f(int);

int main()
{
f(1); // calls f(int)
f<int>(1); // calls f<int>(int);
f<char>(1); // calls f<char>(char);
}

So Visual C++ is correct in not allowing this case and GCC is incorrect. So you are correct about the fix: the class should be declared as (I changed it slightly to make it clearer)

template<typename T>
class Test
{
template<typename U>
friend ostream& operator<< (ostream&, Test<U>&);

};

JonathanCavesMSFT at 2007-10-6 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...
# 2
Thank you very much for your excelent answer.

I changed:

friend ostream&operator<<(ostream&, Test&);

to

friend ostream&operator<< <>(ostream&, Test&);

and it also works.

great_ghost at 2007-10-6 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...