Я получаю ошибку компоновщика при использовании класса шаблона, когда я пытался реализовать идиому копирования и замены, как предложено здесь:
Что такое идиома копирования и обмена?
Класс шаблона, назовем его «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 = (класс 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 )
{
// ...
}
};
Обратите внимание, как мне также пришлось удалять вхождения .