2

私は基本テンプレートを持っています:

template <class X> void f(X x) {}

これで、それを特殊化する 2 つの方法を見てきました。

template <> void f<>(int x) {}

または:

template <> void f<int>(int x) {}

gcc は両方のバリアントを使用しますが、両方を同時に使用することはありません。

これらの 2 つの専門分野は同じですか? テンプレートを特殊化するときに、2 番目の <> で型を指定する必要があるのはいつですか?

4

2 に答える 2

2

2 つの専門分野は同じです。template<>新しい署名を宣言するのではなく、常に既存のテンプレートを特殊化します。特殊化パラメーターの型からの推定によって の内部<>に何が入るかを判断できる場合は、その部分を省略できます。(テンプレートのオーバーロードが多い場合、そのようなものを除外するのは悪い考えかもしれません。どのテンプレートが特化されているかが不明確になる可能性があります。)

ところで、関数を特殊化することは通常悪い考えです。オーバーロードの解決では、テンプレート以外のオーバーロードが優先され、防止したい特殊化が効果的に隠されます。オーバーロードと特殊化のメカニズムを組み合わせるのではなく、オーバーロードに固執してください。

于 2013-07-09T06:40:53.987 に答える
2

両方のバリアントが同じ専門化を実行します。3 番目のバリアントを使用することもできます

template <> void f(int x) {}

の関数テンプレートも特殊化しますX = int。これは、2 番目のバリアントと同等です。

バリアント with f<>and plainfはテンプレート引数推定に依存しますが、f<int>バリアントはテンプレート引数を明示的に指定します。

<>テンプレート引数の推定が不可能な場合は、型を明示的に指定する必要がある場合があります。それ以外の場合は、実行する必要はありません。

たとえば、関数の引数リストがテンプレート パラメーターXに依存していない場合、テンプレート引数を明示的に指定する以外に選択肢はありません。

template <typename X> void bar() {}

template <> void bar<int>() {}

上記がコンパイルされます。しかし、専門分野を次のように置き換えると

template <> void bar<>() {} 

コンパイラはテンプレート引数を推測できないため、コンパイルに失敗します。

于 2013-07-09T06:46:23.737 に答える