2017-06-19 11 views
2

過負荷:C++関数テンプレートの特殊化し、このコードを考慮

template <class T> 
void f(T p) {   //(1) 
    cout << "Second" << endl; 
} 

template <> 
void f(int *p) {  //(2) 
    cout << "Third" << endl; 
} 


template <class T> 
void f(T* p) {   //(3) 
    cout << "First" << endl; 
} 

コールなどint *p; f(p);意志出力First。このような宣言の順序が変更された場合

template <class T> 
void f(T* p) {   //(3) 
    cout << "First" << endl; 
} 


template <class T> 
void f(T p) {   //(1) 
    cout << "Second" << endl; 
} 

template <> 
void f(int *p) {  //(2) 
    cout << "Third" << endl; 
} 

同じコール(int *p; f(p);)が出力Third

私は関数テンプレートのオーバーロードの解決は場所を取るする方法について読む:第1の解像度は非テンプレート関数基礎となるテンプレートを検討します。 "最も特殊化された"ものが選択された後、それがテンプレート関数であり、推論された(または明示的に指定された)パラメータのための特殊化を有する場合、その特殊化が呼び出される。

私の質問は次のとおりです。基底テンプレートの機能は特化ですか?私の例では、関数テンプレートのオーバーロード((1)または(3))は(2)特殊化ですか?

私はスペシャライゼーションが宣言されると、既に宣言されたテンプレートが考慮され、最も特殊な(このスペシャライゼーションに「最も近い」)パラメータが選択されると推測します。これは正しいです?また、標準で指定されている場所を教えてください。

答えて

3

宣言の順序は、実際にどのテンプレートに特化しているかに影響を与えるため、「First」が印刷されます。

この例では、同じ名前をオーバーロードする2つの関数テンプレートがあります。最初のケースでは、void f(T p)を特化しています。これはこれまでに見られた唯一のテンプレートだからです。

2番目のケースでは、それは専門化されたvoid f(T* p)です。そう、はい、あなたの推測は正しいです。詳細は[temp.deduct.decl/1]である:宣言-ID 関数テンプレートの特殊化を指し、テンプレート引数控除が に行われる宣言はを指す専門を識別宣言で

具体的には、明示的なインスタンス化、明示的 特化、および特定のフレンド宣言に対して行われます。 [...]

これには、機能テンプレートの部分的な順序が含まれます。ただし、部分的な順序付けは、特殊化を導入した時点で利用可能な関数テンプレート宣言にのみ適用されます。

とStandardは[temp.expl.spec/7]で警告します:

関数テンプレート、[用明示的な特殊宣言の配置...]、は、明示的な特殊化 宣言とそのインスタンス化のポイントの相対的な配置に従って、上記および下記で指定された変換単位 にプログラムが正しく形成されているかどうかに影響を及ぼします。専門分野を書くときは、その場所について慎重に にしてください。それをコンパイルするには、その自己犠牲に火をつけるようなそのような試行になります。

+0

したがって、特殊化前に宣言されたテンプレート関数から、部分順序を使用して「正しいもの」が選択されますか? – user42768

+0

@ user42768 - テンプレート引数の控除*と*部分的な順序付けによって、はい。 – StoryTeller

関連する問題