Я получаю сообщение об ошибке компоновщика при использовании класса шаблона, в котором я пытался реализовать идиому копирования и замены, как это предлагается здесь:
Что такое идиома копирования и подкачки?
Класс шаблона, назовем его "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 >.