2019年04月14日

クラス・テンプレートのコピー・コンストラクタについて

今日は昼から雨が降り始めました。明日も雨のようです。桜もだいぶ散ってしまいそうです。

散歩の途中で撮影した桜です。毎年、同じような写真をアップロードしているような気がします。
桜

今回はプログラミングの話題です。以下のようなクラス・テンプレートを作成したとします。

template< class T >
class Test
{
public:

  Test( T t )
  { cout << "Test( T t ) called" << endl; }

  template< class U >
  Test( const Test< U >& t )
  { cout << "Test( const Test< U >& t ) called" << endl; }

  template< class U >
  Test& operator=( const Test< U >& t )
  { cout << "Test& operator=( const Test< U >& t ) called" << endl; return( *this ); }
};

次のように使ってみます。

Test< double > testDbl( 1 );
Test< int > testIntCopy( testDbl );
Test< double > testDblCopy( testDbl );
testIntCopy = testDbl;
testDblCopy = testDbl;

今まで、テンプレートを使った任意の型への変換用コンストラクタから、同じ型へのコピー・コンストラクタが作成されるものと思っていました。しかし、実行結果は

Test( T t ) called
Test( const Test< U >& t ) called
Test& operator=( const Test< U >& t ) called

となって、同じ型へのコピー・コンストラクタはコンパイラが自動的に作成したものが使われます。ちゃんと明示したければ、

Test( const Test& t )
{ cout << "Test( const Test& t ) called" << endl; }

Test& operator=( const Test& t )
{ cout << "Test& operator=( const Test& t ) called" << endl; return( *this ); }

という感じに定義してあげないとダメでした。これらを追加すると

Test( T t ) called
Test( const Test< U >& t ) called
Test( const Test& t ) called
Test& operator=( const Test< U >& t ) called
Test& operator=( const Test& t ) called

という風に出力されます。以前作ったプログラムで同じ誤りがあって、よく今まで問題が発生しなかったものだと少し焦りました。その後、「プログラム言語 C++」を見たらちゃんと書いてありました。