I'm getting a linker error when using a template class where I tried implementing the copy-and-swap idiom as suggested here:
What is the copy-and-swap idiom?
The template class, let's call it "TemplateClass" is partially defined like this:
template< class T >
class TemplateClass
{
// ...
TemplateClass< T >& operator= ( TemplateClass< T > other );
friend void swap( TemplateClass< T >& first, TemplateClass< T >& second );
// ...
};
I've put the implementations in a separate TemplateClass.cpp which is included in the .h file. (Edit: I have the same issue if everything is in the .h file)
The assignment operator is defined as:
template< class T >
TemplateClass< T >& TemplateClass< T >::operator= ( TemplateClass< T > other )
{
// copy-and-swap idiom
swap( *this, other );
return *this;
}
and the swap method is defined as:
template< class T >
void swap( TemplateClass< T >& first, TemplateClass< T >& second )
{
using namespace std;
swap( first.member1, second.member1 );
swap( first.member2, second.member2 );
// ...
}
(Don't worry, I do not really name my members "member1" etc)
I have a similar class which is defined in the same way, but is not a template class. Everything works fine there.
However, if I have a class TestClass
which has a member TemplateClass< HandledClass > member
and I make a call in one of its methods like
void TestClass::setMember( TemplateClass< HandledClass > newObject )
{
member = newObject;
}
I get an unresolved external error:
LNK2019: Unresolved external symbol "void __cdecl swap( class TemplateClass &, class TemplateClass &)" (...) in function "public: class TemplateClass X & __thiscall TemplateClass X::operator=(class TemplateClass)" (...) in TestClass.obj
Or in other words:
Something in TestClass
calls TemplateClass<HandledClass>::operator=
which does not find void swap( TemplateClass<HandledClass>, TemplateClass<HandledClass> )
.
So my question is: Why does the operator not find the swap method?
It looks like it was not compiled for the template argument . Is it somehow possible to have the compiler compile friend voids as well?
I could probably ditch the friend void
approach and define an in-class swap method plus an out-of-class swap method plus one in std namespace, but I don't know if it would work that way and I'd like to avoid that if possible anyway.
Solution:
this did the job:
template< class t >
class TemplateClass
{
friend void swap( TemplateClass& first, TemplateClass& second )
{
// ...
}
};
Note how i had to remove the < T > occurrences as well.