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.objError 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
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>&);
};
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.