Ответ 1
В [temp.deduct.type] p5 один из не-выводимых контекстов -
Пакет параметров функции, который не встречается в конце списка объявлений-параметров.
Пакеты параметров, которые не отображаются в качестве последнего аргумента функций шаблона, никогда не выводятся, но совершенно прав, чтобы указать типы параметров, отключающие вычет. например
template<class T1, class ... Types> void g1(Types ..., T1);
g1<int, int, int>(1,2,3); // works by non-deduction
g1(1,2,3) // violate the rule above by non-deduced context
Но изменяя порядок аргумента функции, даже оставляя параметры шаблона такими, какие они есть, удалите неопределенное условие контекста и сломайте бесконечное расширение пакета параметров. например
template<class T1, class ... Types> void g1(T1, Types ...);
g1(1,2,3) // works because its a deduced context.
Есть две причины, по которым ваш код не компилируется:
-
Порядок аргументов функции создает не-выводимый-контекст, который вызывает тип пакета параметров T в шаблоне, указанном в функции f, никогда не будет быть выведено.
-
Параметр шаблона T отображается только как определители в аргументах функции (например, nondeduced_t), а не непосредственно указан как аргумент функции (который позволяет вычесть аргумент).
Чтобы сделать компиляцию кода, вы либо разместите расширение пакета параметров, либо запустив nondeduced_t косвенным, как
template<class... T,class U>
void f( void(*)(U,T...) ) { }
f(g);
или изменить порядок параметров шаблона и указать аргумент шаблона при вызове функции, как
template<class U,class... T>
void f( void(*)(U,typename nondeduced<T>::type...) ) {}
f<int,char>(g);