次のコードでは、main関数はテンプレート関数の代わりに通常の関数を使用しています。
#include <iostream>
using namespace std;
template <class T>
void num(T t){cout<<"T : "<<t;}
void num(int a){cout<<"wT : "<<a;}
int main()
{
num(5);
return 0;
}
この背後にある考えられる理由は何ですか?
次のコードでは、main関数はテンプレート関数の代わりに通常の関数を使用しています。
#include <iostream>
using namespace std;
template <class T>
void num(T t){cout<<"T : "<<t;}
void num(int a){cout<<"wT : "<<a;}
int main()
{
num(5);
return 0;
}
この背後にある考えられる理由は何ですか?
ハーブサッターの優れた記事「関数テンプレートを専門にしないのはなぜですか?」をご覧ください。
引用するには:
「最後に、関数テンプレートのみに焦点を当て、オーバーロードルールを検討して、さまざまな状況で呼び出されるルールを確認しましょう。ルールは、少なくとも高レベルでは非常に単純であり、古典的な2クラスシステムとして表現できます。
非テンプレート関数は第一級市民です。パラメータタイプおよび任意の関数テンプレートに一致する単純な古い非テンプレート関数が、他の点では適切な関数テンプレートよりも選択されます。
少なくとも同じくらい良い一級市民がいない場合は、次に二級市民と同じように機能ベースのテンプレートを参照します。どの関数ベーステンプレートが選択されるかは、どれが最もよく一致し、「最も専門的」であるかによって異なります(重要な注意:この「専門的」の使用は、奇妙なことに、テンプレートの専門化とは関係ありません。不幸な口語表現です)。難解なルール:
「最も特殊な」関数ベーステンプレートが1つあることが明らかな場合は、そのテンプレートが使用されます。そのベーステンプレートが使用されているタイプに特殊化されている場合は、特殊化が使用されます。それ以外の場合は、正しいタイプでインスタンス化されたベーステンプレートが使用されます。
それ以外の場合、「最も特殊な」関数ベーステンプレートが同点の場合、コンパイラはどちらがより適切かを判断できないため、呼び出しはあいまいになります。プログラマーは、呼び出しを修飾し、どれが必要かを言うために何かをしなければなりません。
そうでなければ、一致させることができる関数ベースのテンプレートがない場合、呼び出しは正しくなく、プログラマーはコードを修正する必要があります。」
コード例では、David Z.が指摘しているvoid num(int a)
ように、最初のルールで一致するため、非テンプレート関数が選択されます。追加の関数テンプレートは、それらがより適切に一致する場合にのみ考慮されます。
この場合にテンプレートメソッドを呼び出すには、のnum<int>(5)
代わりに明示的にメソッドを呼び出す必要がありますnum(5)
。コンパイラーは推測できますが、ジェネリック方式よりも非ジェネリック方式の方が適しています。この動作はhttp://ideone.com/ccDJPで確認できます。