置き換えX
てint
、どのプライマリ テンプレートが一致するシグネチャを生成するかを確認します。
template<class X> void foo(X a)
になる
template <> void foo<int>(int)
と
template<class X> void foo(X *a)
になる
template<> void foo<int>(int *)
したがって、それは 2 番目の関数の特殊化にすぎません。関数は最初のオーバーロードを特殊化しないため、特殊化を定義する前に 2 番目のプライマリ テンプレートを宣言する必要があります。これは、特殊化が最初のプライマリ テンプレートを特殊化できないためです。
テンプレート引数が特殊化で明示的に指定されていない場合、関連するプライマリ テンプレートは、14.8.2.6 [temp.deduct.decl] パラグラフ 1 に従って、通常の引数控除規則を使用して検出されます。
declarator-id が関数テンプレートの特殊化を参照する宣言では、宣言が参照する特殊化を識別するために、テンプレート引数推定が実行されます。具体的には、これは明示的なインスタンス化 (14.7.2)、明示的な特殊化 (14.7.3)、および特定のフレンド宣言 (14.5.4) に対して行われます。
この引数推定では、プライマリ テンプレートの部分的な順序付けが考慮されます。つまり、2 番目のプライマリ テンプレートが検出されます。私はリメリックに至るまでのパラグラフを読むという罠に陥りませんでしたが、警告は本当です: 2 番目のプライマリ テンプレートと特殊化の順序を変更すると、問題が発生すると思います! 前述の焼身自殺について警告されていることに注意してください。