ページ 11

コピーコンストラクタが呼び出されないことの解決方法

Posted: 2013年5月17日(金) 02:03
by dom
以下のコードについてです。クラスPiyoのコンストラクタ内でのポインタの初期化時に
Hogeのコピーコンストラクタが呼ばれてほしいのですが、テンプレート版の方が呼ばれてしまいます。
何かスマートな解決法はないでしょうか?

コード:

class Hoge
{
public:
	template <class T>
	explicit Hoge(T& val) { cout << "template" << endl; }

	Hoge(const Hoge& other) { cout << "copy ctor" << endl; }
};

class Piyo
{
public:
	template <class T>
	Piyo(T& val)
		: ptr(new T(val)) // コピーコンストラクタ呼び出しのつもりが、呼ばれない
	{}
private:
	shared_ptr<void> ptr;
};

int main()
{
	int forTemplate = 123;
	Hoge hoge( forTemplate ); // テンプレート版コンストラクタをよぶ
	Piyo piyo( hoge );  // hogeを内部でコピーして保持したい

	return 0;
}

Re: コピーコンストラクタが呼び出されないことの解決方法

Posted: 2013年5月17日(金) 02:44
by YuO
Piyoのコンストラクタのシグネチャを,

コード:

Piyo (const T& val)
とするか,
初期化子を,

コード:

: ptr(new T(const_cast<const T &>(val))
とすればよいでしょう。

コード:

template Hoge<Hoge>(Hoge &)

コード:

Hoge (const Hoge &)
の間で,

コード:

new Hoge( /* val : Hoge & */ val)
のオーバーロードでは,前者は変換が0回に対して後者はHoge &からconst Hoge &への変換が1回あるため,前者が選ばれます。
後者に対して変換が0回になるようにしてやることで,後者を選ぶようになります。

Re: コピーコンストラクタが呼び出されないことの解決方法

Posted: 2013年5月17日(金) 11:47
by dom
返信ありがとうございます。変換回数で決まるとは知りませんでした。
おかげで知識が増えました。ありがとうございます。