2013-06-12 16 views
5

推測されたテンプレートは間違っているようですが、(b)ではなく(c)が呼び出されたのはなぜですか?テンプレートの控除が間違っているようです

#include <iostream> 
using namespace std; 
template<class T> void f(T){cout << "f(T)";}//(a) 
template<> void f<>(int*){cout << "f(int*)";}//(b) 
template<class T> void f(T*){cout << "f(T*)";}//(c) 
//void f(int*){cout <<"POD:f(int*)";}//(d) 

int main(int argc,char*argv[]) 
{ 
    int p = 1; 
    f(&p); 
    cout <<endl; 
    return 0; 
} 

出力:

f(T*)

+7

参照[なぜ関数テンプレートを専門ではない](http://www.gotw.ca/publications/mill17.htm)。 – juanchopanza

+1

@jogojapan質問をよりよく反映するために、複製のタイトルを変更しました。 – juanchopanza

答えて

3

[OK]を、我々が最初に持ってまっすぐに何を設定してみましょう。

(a)は関数テンプレートです。 (b)は、その機能テンプレートの特殊化です。 (c)は、(a)をオーバーロードする別の関数テンプレートです。

f(&p)と書くときは、2つの関数テンプレート(a)と(c)の2つのオーバーロードを考慮する必要があります。 (c)ではT*が(a)のTよりも特殊なので、(c)が選択されます。

ここで、コメントアウト(d)を考えてみましょう。これは関数テンプレート(a)の特殊化ではなく、追加のオーバーロードです。 f(&p)コールを解決するには、考慮すべき3つのオーバーロードがあります。 (d)はテンプレートではなく、タイプ&pに一致するint*があるため、他の2つ以上で選択されます。

+0

(bx)は既に(d)というコードになっています:) – yuan

+0

@yuan oh。私の目はコメントされたコードを読んでいるだけです。ダミット、彼らはあまりにも訓練されている:( –

0

テンプレートの特殊化がテンプレートの後に来る必要があります。 はここで、あなたのケースでは、それは次のようになります。

template<class T> void f(T){cout << "f(T)";}//(a) // Template 1 
template<> void f<>(int*){cout << "f(int*)";}//(b) // Specialization of template 1 
template<class T> void f(T*){cout << "f(T*)";}//(c) // Template 2, conceals template 1 

は、したがって、あなたがインスタンス化されたテンプレート2を取得します。 TOIはそれを行う 正しい方法は次のとおりです。

template<class T> void f(T*){cout << "f(T*)";} // Template 1 
template<class T> void f(T){cout << "f(T)";} // Template 2 
template<> void f<>(int*){cout << "f(int*)";} // Specialization of the template 1 

が出力:

f(int*) 
関連する問題