Получавам грешка при свързване, когато използвам шаблонен клас, където се опитах да внедря идиома за копиране и размяна, както е предложено тук:
Какво представлява идиомът за копиране и размяна?
Класът на шаблона, нека го наречем "TemplateClass", е частично дефиниран по следния начин:
template< class T >
class TemplateClass
{
// ...
TemplateClass< T >& operator= ( TemplateClass< T > other );
friend void swap( TemplateClass< T >& first, TemplateClass< T >& second );
// ...
};
Поставих имплементациите в отделен TemplateClass.cpp, който е включен в .h файла. (Редактиране: имам същия проблем, ако всичко е във файла .h)
Операторът за присвояване се дефинира като:
template< class T >
TemplateClass< T >& TemplateClass< T >::operator= ( TemplateClass< T > other )
{
// copy-and-swap idiom
swap( *this, other );
return *this;
}
и методът на суап се дефинира като:
template< class T >
void swap( TemplateClass< T >& first, TemplateClass< T >& second )
{
using namespace std;
swap( first.member1, second.member1 );
swap( first.member2, second.member2 );
// ...
}
(Не се притеснявайте, аз всъщност не наричам членовете си "member1" и т.н.)
Имам подобен клас, който е дефиниран по същия начин, но не е шаблонен клас. Там всичко работи добре. Ако обаче имам клас TestClass
, който има член TemplateClass< HandledClass > member
и направя повикване в един от неговите методи като
void TestClass::setMember( TemplateClass< HandledClass > newObject )
{
member = newObject;
}
Получавам неразрешена външна грешка:
LNK2019: Неразрешен външен символ "void __cdecl swap( class TemplateClass &, class TemplateClass &)" (...) във функция "public: class TemplateClass X & __thiscall TemplateClass X::operator=(class TemplateClass)" (...) в TestClass.obj
Или с други думи: нещо в TestClass
извиква TemplateClass<HandledClass>::operator=
, което не намира void swap( TemplateClass<HandledClass>, TemplateClass<HandledClass> )
.
Та въпросът ми е: Защо операторът не намира метода за размяна?
Изглежда, че не е компилиран за аргумента на шаблона. Възможно ли е по някакъв начин компилаторът да компилира и приятелски празнини?
Вероятно бих могъл да се откажа от подхода friend void
и да дефинирам метод за суап в клас плюс метод за суап извън клас плюс един в пространството на имената std, но не знам дали ще работи по този начин и бих искал да избегна това ако е възможно все пак.
Решение:
това свърши работа:
template< class t >
class TemplateClass
{
friend void swap( TemplateClass& first, TemplateClass& second )
{
// ...
}
};
Забележете как трябваше да премахна и срещанията ‹ T >.