2013-05-31 9 views
10

驚いたことに、このプログラムは、MSCVとGCCの両方でコンパイルされます。メソッド名

明らか
class A 
{ 
public: 
    int add() { return 0; } 
    template<typename T> 
    T add() { return T(); } 
}; 

int main() { 
    A a; 
    a.add(); 
    a.add<int>(); 
    return 0; 
} 

、によるテンプレート方式の種類を推定し、する必要がありますすることができないという事実に明確に述べられているので、明らかに間違っているテンプレート化されていない方法であれば、状況はあいまいではありません。

私は、標準の最後のドラフトを見てみましたが、答えを見つけることができませんでした - テンプレートメソッドの同じ命名法と、C++の戻り値の型が違う通常のメソッドコンパイラはただ許可していますか?

答えて

10

これは常に正当なC++でした。

14.5.6/2:

関数テンプレートは、他の関数テンプレートとし、通常の(非テンプレート)機能をオーバーロードすることができます。通常の機能は、潜在的に生成される機能テンプレートの専門化と同じ名前およびタイプを有する場合であっても、機能テンプレートに関連しない(すなわち、専門化であるとは決して考えられない)。

add<int>のような「template-id」構文を使用すると、十分なテンプレートパラメータを持つテンプレート関数のみが考慮されます。だからa.add<int>()は、テンプレート以外のテンプレートaddが一致するかどうかを調べていません。

識別子がプレーン関数と関数テンプレートの両方に名前を付けると、コンパイラは関数テンプレートのテンプレート引数を推定し、テンプレート関数の特殊化を取得しようとします。その後、すべてのプレーン関数とすべてのテンプレート関数の特殊化は、通常の関数のオーバーロードロジックによって比較されます。 [13.3.1/7を参照]

この例では、a.add()というコールは、テンプレートバージョンのテンプレート引数Tを推定できません。したがって、唯一実行可能な機能はテンプレート以外のオーバーロードです。

同様の状況で起こるもう1つのルールもあります。テンプレート以外の関数とテンプレート関数の特殊化があいまいなオーバーロードの場合、テンプレート以外の関数が勝ちます。 [このルールは、1つの引数のセットに対して別のより良い機能するものの定義の途中で、セクション13.3.3である。]

class B 
{ 
public: 
    int f(int n) { return n+1; } 

    template<typename T> 
    T f(T n) { return n; } 
}; 

int main() { 
    B b; 
    b.f(1);  // both are viable, non-template wins 
    b.f<int>(1); // only the template is viable 
    return 0; 
} 

テンプレートがまだで使用することができますので、これは理にかなっています他の特殊化、または山括弧>を明示的に使用して、したがって、テンプレート以外の関数を使って関数テンプレートをオーバーロードすることは、明示的な特殊化を追加するようなものですが、頭痛が少なくなります。

+0

うわー、後者はさらに面白いです - これを念頭に置いておきます、ありがとう! –

関連する問題