これはquestionと似ていますが、より具体的なケースです。今回は、期待通りにコンパイラが動作しません。上記の例でテンプレートの引き数は、推論されていないパラメーターパックを含む関数ポインターのパラメータータイプのために控除します。
template<class T>
struct nondeduced
{
using type = T;
};
template<class T>
using nondeduced_t = typename nondeduced<T>::type;
template<class... T, class U>
void f(void(*)(nondeduced_t<T>..., U)) {}
void g(int, char) { }
int main()
{
f<int>(g); // error?
}
、パラメータパックT
を推定することはできないが、コンパイラは、パックT
(この場合、すなわち単一int
)の明示的な引数置換後U
を推定することができなければなりません。
template<class... T, class U>
void f(void(*)(T..., U)) {}
パラメータパックT
非演繹 [temp.deduct.type]p5
に係る非推定コンテキストに既に存在するので上記同様
nondeduced_t
トリックなしで動作することが期待されるコンテキストは次のとおりです。
- 関数のパラメータパラメタ宣言リストの最後には現れない。
残念ながら、私がテストなしコンパイラ(G ++ /打ち鳴らす)がコードを受け入れません。 特に以下のようなものはg ++ & clangで動作します。
template<class... T>
void f(void(*)(nondeduced_t<T>..., char)) {}
そして再び、これは両方の上では動作しません:
template<class... T>
void f(void(*)(T..., char)) {}
は私の予想が間違ってますか? 非推測コンテキストの[temp.deduct.type]p5一つによって
ここで少し勉強してください。私は 'template void f(void(*)(nondeduced_t ...、U)){}'は、variadicパラメータパックが最初に出現しているため。 –
AndyG
@AndyG from cppreference:[プライマリクラステンプレートでは、テンプレートパラメータパックは、テンプレートパラメータリストの最後のパラメータでなければなりません。関数テンプレートでは、次のすべてのパラメータを関数引数から導き出すことができるか、または既定の引数を持つことができるという条件で、テンプレートパラメータパックがリストの先頭に表示されます(http://en.cppreference.com/w/cpp/language/ parameter_pack) – jaggedSpire
これはspeccccによって明示的に指定されていないようです –