ここで提案されているように、コピーアンドスワップイディオムを実装しようとしたテンプレートクラスを使用すると、リンカーエラーが発生します。
テンプレートクラスを「TemplateClass」と呼びましょう。部分的に次のように定義されています。
template< class T >
class TemplateClass
{
// ...
TemplateClass< T >& operator= ( TemplateClass< T > other );
friend void swap( TemplateClass< T >& first, TemplateClass< T >& second );
// ...
};
.hファイルに含まれている別のTemplateClass.cppに実装を配置しました。(編集:すべてが.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
、そのメソッドの1つで次のような呼び出しを行う場合
void TestClass::setMember( TemplateClass< HandledClass > newObject )
{
member = newObject;
}
未解決の外部エラーが発生します:
LNK2019:関数 "public:class TemplateClass X&__ thiscall TemplateClass X :: operator =(class TemplateClass)"(...)の未解決の外部シンボル "void __cdecl swap(class TemplateClass&、class TemplateClass&)"(...) TestClass.obj内
または言い換えると、TestClass
呼び出しTemplateClass<HandledClass>::operator=
で何かが見つからないvoid swap( TemplateClass<HandledClass>, TemplateClass<HandledClass> )
。
だから私の質問は:なぜオペレーターはスワップメソッドを見つけられないのですか?
テンプレート引数用にコンパイルされていないようです。コンパイラにフレンドボイドもコンパイルさせることはどういうわけか可能ですか?
私はおそらくfriend void
アプローチを捨てて、クラス内のスワップメソッドとクラス外のスワップメソッドとstd名前空間の1つを定義することができますが、それがそのように機能するかどうかはわかりません。とにかく可能です。
解決:
これは仕事をしました:
template< class t >
class TemplateClass
{
friend void swap( TemplateClass& first, TemplateClass& second )
{
// ...
}
};
<T>オカレンスも削除する必要があることに注意してください。