2015-09-12 16 views
5

テンプレートコピーコンストラクタを持つテンプレートクラスがあります。問題は、このクラスを同じテンプレートタイプの別のインスタンスを使用してインスタンス化するときです。テンプレートコピーコンストラクタは呼び出されません。なぜそれは一致しないのですか?ここ は、コードスニペットです:テンプレートクラスのC++テンプレートコピーコンストラクタ

#include <iostream> 

template <typename T> 
class MyTemplateClass 
{ 
    public: 
     MyTemplateClass() 
     { 
      std::cout << "default constructor" << std::endl; 
     } 

     /* 
     MyTemplateClass(const MyTemplateClass<T>& other) 
     { 
      std::cout << "copy constructor" << std::endl; 
     } 
     */ 

     template <typename U> 
     MyTemplateClass(const MyTemplateClass<U>& other) 
     { 
      std::cout << "template copy constructor" << std::endl; 
     } 
}; 

int main() 
{ 
    MyTemplateClass<int> instance; 
    MyTemplateClass<int> instance2(instance); 
    return EXIT_SUCCESS; 
} 

出力は

default constructor 

あるしかし、私は明示的に(それをコメント解除することによって)デフォルトのコピーコンストラクタを書いた場合、出力は

default constructor 
copy constructor 

なり私は本当にそれを取得していません。私はローカルコンパイラ(clang-500.2.79)とthis one(gcc 4.9.2)でテストして同じ結果を得ました。

+5

テンプレートは決してコピーコンストラクタではありません! –

+5

コピーコンストラクタは決してテンプレートではありません。 –

+0

オーバーロード解決が推奨する暗黙的に宣言されたコピーコンストラクタがあります。 –

答えて

2

コピーコンストラクタの形式はX(X&)または(X const&)で、宣言していない場合(またはここでは関係のないいくつかの条件)、コンパイラによって提供されます。あなたはその暗黙のうちに私たちは候補者の次のセットを持って、しませんでした:

MyTemplateClass(const MyTemplateClass&); 
template <typename U> MyTemplateClass(const MyTemplateClass<U>&); 

の両方が

MyTemplateClass<int> instance2(instance); 

の両方に生存しているとまったく同じ引数を取ります。問題は、コピーコンストラクタテンプレートがと一致していないということではありません。と一致しています。問題は、暗黙のコピーコンストラクタが関数テンプレートではなく、オーバーロード解決になると、テンプレート以外のテンプレートがテンプレートの特殊化よりも優先されるということです。 [over.match.best]、無関係な箇条書きを省略:これらの定義を考えると

を、実行可能な関数F1は、別の実行可能な機能 F2よりも良い関数であると定義されている場合、すべての引数iについて、ICS I(F1)ICS 以下悪い変換シーケンスであるI(F2)、次いで
- [...]
- F1ない関数テンプレート特殊化であり、F2は、関数テンプレート特殊化であるか、または、そうでなければ、
- [...]

これは、あなたのコンストラクターテンプレートに対して暗黙の(そしてあなたの明示的な)コピーコンストラクターを呼び出す理由です。

+0

オーバーロードの解像度に関するテンプレート以外のテンプレートをテンプレート特殊化に使用するのはなぜですか?ほとんどの場合、それは選択するのが最良の戦略ですか? – syntagma

+1

@REACHUSこれはルール(標準引用文が追加されている)であるため、直接答えがあります。一般的なルールは、可能な最も具体的な機能を選択することです。非テンプレートはテンプレートよりも具体的です。 – Barry

+0

Okタンク、私の間違いはコピーコンストラクタが生成されないと思うことでした。 – Jairard

2

コードにコピーコンストラクタがない場合、コンパイラは暗黙的にコードを生成します。この行が実行されたときにそのため:

MyTemplateClass<int> instance2(instance); 

コピーコンストラクタは、しかし、明らかに、あなたの実行されてではありません。私はテンプレートはそれとは関係ないと思う。

ここでそれについて詳しく読む:Implicitly-defined copy constructor

-1

を私はREACHUSが正しい(それはあまりにも非テンプレートクラスと同じように)、コンパイラはデフォルトのコピーコンストラクタを生成しているし、それはだとして、あなたのテンプレート上でこれを好むと思いますより専門的。 "普通の"コピーコンストラクタをprivateにするか、C++ 11の 'deleted'キーワードを使用して関数を使用できないものとしてマークするのがよいでしょう。編集:これはコンパイルされません、申し訳ありません、私はその時点でそれをテストすることができませんでした。

+0

これらの提案はどちらも、コードをコンパイルできないようにします。コンストラクタテンプレートを呼び出すことは好まれません。 – Barry

+0

@Barryなぜこの場合、削除されたコピーコンストラクタを宣言するのは良い考えではないと思いますか? – syntagma

+0

@REACHUSこれは、クラスをコピー不可能にします。私はそれがOPの目標であるとは思わない。 – Barry

関連する問題