5

関数テンプレートを部分的に特殊化することはできませんが、標準的な関数のオーバーロードも理解しています。関数の特殊化/オーバーロードのルールの例

私が助けが必要なのは、以下の4つのfoo()関数の違いを突き止めることです。私はそれらのいくつかがまったく同じものの構文が異なることを期待していますか?

誰かが各機能について正確に何が起こっているのかは、それがテンプレートの特殊化または過負荷ですか、そしてどのようにして呼び出すべきかをC++コンパイラが決定するのでしょうか?

//(1) 
template<typename T> 
void foo(T t) 
{ 
    cout << "template<T> foo(T) " << endl; 
} 

//(2) 
template<> 
void foo<int*>(int* l) 
{ 
    cout << "template<> foo<int*>(int*) " << endl; 
} 

//(3) 
template<typename T> 
void foo(T* l) 
{ 
    cout << "template<T> foo(T*) " << endl; 
} 

//(4) 
void foo(int* l) 
{ 
    cout << "normal overload foo(int*) " << endl; 
} 

int main() 
{ 
    int x = 0; 
    foo(x); 
    foo(&x); 
    return 0; 
} 

プログラム出力:コメント欄で

template<T> foo(T) 
normal overload foo(int*) 
+0

@ Rakete1111あなたは正しいです。編集されました。 – Jordan

答えて

1

最初の呼び出しであるfoo(x)を試してみましょう。

intパラメータを推定することができない、ポインタのように記述することはできません、次の

void foo(int* l); 

は、暗黙的にint*intを変換できません、次の

template<typename T> 
void foo(T t); 

良い試合のように思えます、2)と覚えているように。次

template<> 
void foo<int*>(int* l); 

は)だから、唯一の可能なマッチが2で、暗黙的にint*の隣に

template<typename T> 
void foo(T* l) 

intを変換することはできませんし、そうtemplate<T> foo(T)が出力されます。


第2の呼び出しは、foo(&x)です。

void foo(int* l); 

xのタイプに完全に一致する非テンプレート関数です。これを覚えておきましょう。

template<typename T> 
void foo(T t); 

いいね!しかし、以前のものはまだ良いです、

template<> 
void foo<int*>(int* l); 

次のああ、丁度タイプに一致する前のテンプレートの特殊化は、それは良いでしょうが、1)まだ良く一致しています。次の

特殊化よりも優れていますが、テンプレートはありませんが、テンプレート以外のものには勝っていません。

最後に、非テンプレート関数が呼び出されます。テンプレート以外は常にテンプレートよりも優れています。

+0

オーバーロードの分解能は基本テンプレートのみを選択するので、2)過負荷の解決前に選択することはできません。 http://www.gotw.ca/publications/mill17.htm –

+0

@VS特殊化があるので、基本テンプレートの過負荷が選択されないことを意味しますか – Rakete1111

+1

「どの基本テンプレートを選択するか決定した後で、その選択肢は固定されています。コンパイラは、使用可能なテンプレートの適切な特殊化が起こっているかどうかを見て回り、特殊化が使用されるかどうかを調べます。つまり、テンプレートの特殊化は過負荷の後で見られます。 –

5

説明:

// the 1st primary function template, overloaded function template 
template<typename T> 
void foo(T t) 

// full template specialization of the 1st function template with T = int* 
template<> 
void foo<int*>(int* l) 

// the 2nd primary function template, overloaded function template 
template<typename T> 
void foo(T* l) 

// non-template function, overloaded function 
void foo(int* l) 

int main() 
{ 
    int x = 0; 
    foo(x); // only match the 1st function template; the others take pointer as parameter 
    foo(&x); // call the non-template function, which is prior to templates in overload resolution 
    return 0; 
} 

overload resolutionexplicit (full) template specializationの詳細を参照してください。

0

template<typename T> void foo(T t)以外の候補機能がないため、foo(x)の解決方法は簡単に見つけることができます。

foo(&x)の理由でvoid foo(int* l)と表示されるのはなぜですか?

  1. テンプレートメソッドtemplate<> void foo<int*>(int* l) を呼び出すために、あなたはあなたが見ることができるようにfoo<int*>(&x)

を呼び出すことにより、foo<int>(&x)

  • template<typename T> void foo(T t)を呼び出すことによってfoo<int*>(&x)
  • template<typename T> void foo(T* l)を呼び出す必要があり、foo(&x)を呼び出すことはしません明示的なテンプレートで上記の3つのスタイルのいずれかと一致します。専門的な機能void foo(int* l)、関数呼び出しfoo<int*>(&x)の不在に特化しテンプレート機能template<> void foo<int*>(int* l)どの機能を決定しようとすると非専門的なテンプレート機能template<typename T> void foo(T t)

  • +0

    特別な関数 'void foo(int * l)'がなければ、テンプレート 'foo(&x)'に対して ' void foo(T * l)'が呼び出されます。 –

    0

    を打つことによって解決されるだろうと

    注意オーバーロード時に呼び出されます。最小限の最適化が必要な関数を常に見つけます。

    foo()がintで呼び出された場合、intをint *に変換することができないため、使用できる唯一の関数が最初の関数です。

    int *:
    関数4を使用すると、最適化せずに使用できます。
    関数3は、実行するためにT-> intを変更する必要があります。
    関数1は、Tをポインタ型に変更し、Tがintを指していると判断する必要があります。
    関数2 SO 4は、テンプレートタイプを更新する2人のニーズ、直ちに機能を使用することができる機能

    機能1の特殊化であり、テンプレート・タイプ、およびオブジェクトタイプを更新するために、1,2のニーズに機能します。
    この順番で呼び出されます:4,3次に2そして1

    関連する問題