4

なぜテンプレートの特殊化が理にかなっているのだろうか?

次のことは同等ではありませんか?

テンプレートの専門化:

template <typename T>
void f(T t) {
  something(t);
}

template <>
void f<int>(int t) {
  somethingelse(t);
}

特殊化ではなく非テンプレート関数:

void f(int t) {
  somethingelse(t);
}

非テンプレート関数が常に優先されるため、これらは同じであると思います。

4

4 に答える 4

4

これが私が思いついた答えです:

テンプレート パラメーターが定義されている関数のパラメーターでない場合は異なります。

template <typename T>
void f() {
  T t;
  something(t);
}

template <>
void f<int>() {
  int t;
  somethingelse(t);
}

この場合、以下を定義します。

void f() {
  int t;
  somethingelse(t);
}

すべてのテンプレート バージョンが使用できなくなります。

他の誰かがより良いアイデアを持っているかもしれません。:)

于 2012-08-01T11:22:59.543 に答える
3

のように呼び出すことに固執する場合、関数を宣言する方法f<int>(42)重要です。これにより、特殊化が検出されますが、オーバーロードは検出されません。

呼び出しが常に のように見える場合はf(42)、どちらの方法でも機能します。

于 2012-08-01T12:17:24.407 に答える
3

問題は、オーバーロードが使用できない特殊化がいつ使用されるかを決定することに要約されます。これが当てはまるさまざまな状況がありますが、それらは非常にまれですが、間違いを犯すのは簡単であるため、一般的な推奨事項は特殊化よりもオーバーロードを優先することです。

  • 呼び出し元がテンプレートの使用を明示的に要求した場合。提供するコード例では、呼び出しがf<int>(42)または でf<42>()ある場合、オーバーロードは使用されません。

  • 必要なオーバーロードを提供できない場合、または呼び出しの場所でオーバーロードを解決できない場合。たとえば、型が関数の引数の 1 つでない場合 (シグネチャにまったく存在しないか、戻り値の型にのみ存在します。

    テンプレート T f();

この場合、オーバーロードint f();を提供することはできませんdouble f();が、必要な数のテンプレートの特殊化を提供することはできます。いずれかの選択を強制するのはユーザー次第です。これは前のケースのサブケースと見なすことができることに注意してください: テンプレート引数は関数引数に関与しないため、ユーザーはテンプレート引数を提供する必要があるため、呼び出しは明示的にテンプレートになります。

  • 引数の組み合わせに特別な制約を課し、暗黙的な変換を禁止したい場合:

    テンプレート void f( T, T ); // 両方の引数は同じ型でなければなりません

テンプレート引数推定は完全一致のみを実行するため、このテンプレートは両方の引数がまったく同じ型である場合にのみ使用できvoid f(int,int)ます。f( 5, 3.0 )専門分野はそうではありません。

一般に、ほとんどの場合、上記のケースのどれも実際には当てはまらないため、オーバーロードを優先する必要があります。


他にもあるかもしれませんが、頭の中で思い出せるのはこれらだけです

于 2012-08-01T12:47:38.690 に答える
0

関数テンプレートの特殊化は、1つの例外を除いて、関数のオーバーロードを優先して非推奨になりました。std名前空間に関数テンプレートの特殊化を追加することは許可されていますが、新しい関数を追加することは許可されていません。したがって、std名前空間内の何かに特定のバージョンを提供する必要がある場合は、テンプレートの特殊化を使用する必要があります。たとえば、ユーザー定義クラスをキーとしてunordered_mapの作成をサポートするには、クラス用にstd::hashを特殊化する必要があります。

于 2012-08-13T16:49:58.613 に答える