次のコードは、私が知っているように、「推測されたコンテキストではない」(またはそうでない) 必要があります。
template <class... X, class Y>
void f(X... args, Y y)
{
}
int main()
{
f(12);
f<int, int, int>(1, 2, 3, 4);
}
しかし、g++ 4.9 は in の両方のインスタンス化のためにそれをコンパイルしますf
...main
誰か説明できますか?
次のコードは、私が知っているように、「推測されたコンテキストではない」(またはそうでない) 必要があります。
template <class... X, class Y>
void f(X... args, Y y)
{
}
int main()
{
f(12);
f<int, int, int>(1, 2, 3, 4);
}
しかし、g++ 4.9 は in の両方のインスタンス化のためにそれをコンパイルしますf
...main
誰か説明できますか?
最初の呼び出しf(12)
の形式が正しくありません。パラメーター宣言の最後に表示されないパラメーター パックは、[temp.deduct.type]/p5.7 による非推定コンテキストです。
非推定コンテキストは次のとおりです。
— [..]
— parameter-declaration-listの末尾にない関数パラメーター パック
さらに [temp.deduct.call]/p1 で:
parameter-declaration-listの末尾にある関数パラメーター パックの場合
A
、呼び出しの残りの各引数の型が、関数パラメーター パックの declarator-id の型と比較されP
ます。各比較は、関数パラメーター パックによって展開されたテンプレート パラメーター パック内の後続の位置のテンプレート引数を推測します。関数パラメーター パックが推定されないコンテキスト (14.8.2.5) に表示される場合、そのパラメーター パックの型は推定されません。[ 例:
template<class ... Types> void f(Types& ...); template<class T1, class ... Types> void g(T1, Types ...); template<class T1, class ... Types> void g1(Types ..., T1); void h(int x, float& y) { const int z = x; f(x, y, z); // Types is deduced to int, float, const int g(x, y, z); // T1 is deduced to int; Types is deduced to float, int g1(x, y, z); // error: Types is not deduced g1<int, int, int>(x, y, z); // OK, no deduction occurs }
— 終了例 ]
したがって、パラメーター パックX...
は関数の引数によって推測できず、テンプレート引数の推測は失敗します。GCC は、推測しない12
ためにテンプレートを拒否するのではなく、最初の呼び出しを受け入れるため、バグのようです。
ただし、 2 番目の呼び出しはf<int, int, int>(1, 2, 3, 4)
、[temp.deduct]/p6 に従って整形式です。明示的に指定されたテンプレート引数は、関数テンプレートのテンプレート パラメーターにすぐに置き換えられます。これはX = {int, int, int}
. 次に、テンプレートの引数推定は、次Y
のように右端の引数から推定されますint
。
テンプレート引数推定プロセスの特定の時点で、テンプレート パラメーターを利用する関数型を取得し、それらのテンプレート パラメーターを対応するテンプレート引数に置き換える必要があります。これは、明示的に指定されたテンプレート引数が関数型に代入されるときにテンプレート引数推定の開始時に行われ、デフォルト引数から推定または取得されたテンプレート引数が置換されるときにテンプレート引数推定の最後に再度行われます。
([temp.deduct]/p2):
少なくとも 1 つのパラメーターがテンプレート パラメーター pack でない限り、パラメーターよりも多くの引数があってはなりません。また、非パック パラメーターごとに引数が存在する必要があります。
Clang は最後の関数呼び出しを受け入れませんが、GCC は受け入れます。これは Clang のバグだと思います。
parameter-pack の発生に続く default-arguments の使用に関して、未解決のCWG 問題 1609があることに注意してください。そのコンテキストでの Clang の動作に異議を唱えるLLVM Bug 21774もあります。