С этого упомянутого пункта:
Если шаблон-параметр шаблона класса, переменной шаблона или шаблона псевдонима имеет шаблонный аргумент по умолчанию, каждый последующий шаблон-параметр должен либо иметь template- по умолчанию аргумент предоставлен или является пакетом параметров шаблона. Если шаблон-шаблон шаблона первичного класса, шаблон первичной переменной или шаблон псевдонима является пакетом параметров шаблона, он должен быть последним параметром шаблона. Пакет параметров шаблона функции не должен сопровождаться другим параметром шаблона , если только этот параметр шаблона не может быть выведен из списка параметров-типа ([dcl.fct]) шаблона функции или имеет аргумент по умолчанию ([temp.deduct]). Параметр шаблона шаблона руководства дедукции ([temp.deduct.guide]), который не имеет аргумента по умолчанию, должен выводиться из списка типов параметров шаблона руководства по вычитанию. [Пример:
template<class T1 = int, class T2> class B; // error
// U can be neither deduced from the parameter-type-list nor specified
template<class... T, class... U> void f() { } // error
template<class... T, class U> void g() { } // error
- конец пример]
В этом случае template<typename... A, typename R>
не может быть выведена из параметров для типа списка шаблона функции, потому что с:
void f(A&&..., R(*)(A...))
A&&...
является жадным, и он будет потреблять g
как A&&
не R(*)(A...)
Говоря педантично, как в temp.deduct.call-1:
Для параметра функции пакета, что происходит в конце параметр декларирования-лист, удержание выполняется для каждого оставшегося аргумента вызова, принимая тип Р declarator-id пакета параметров функции как соответствующий тип параметра шаблона функции. Каждый вывод выводит аргументы шаблона для последующих позиций в пакетах шаблонов параметров, расширенных пакетом параметров функции. Когда пакет параметров функций появляется в невыводимом контексте ([temp.deduct.type]
), тип этого пакета параметров не выводится.
как и в temp.deduct.type#9:
Если P имеет форму, которая содержит < T> или < я>, то каждый аргумент Pi соответствующего шаблона списка аргументов Р сравнивается с соответствующим аргумент Ai соответствующего списка аргументов шаблона A. Если список аргументов шаблона из P содержит расширение пакета, которое не является последним аргументом шаблона, весь список аргументов шаблона является невыводимым контекстом. Если Pi является пакет расширения, то модель Pi сравнивается с каждым оставшимся аргументом в списке аргументов шаблона А.
И это не может быть определено, как вы можете увидеть в третьем примере.
clang is right when reject it.
Что происходит, когда прототипом является 'R (*) (A ...), A && ...'? Я думаю, что «clang» прав, потому что пакет аргументов должен проглотить указатель на функцию, следовательно, не выводить «R». – StoryTeller
@StoryTeller Хорошая точка. Оба компилятора принимают код. Во всяком случае, это не совсем то же самое. Перемещение указателя функции также позволяет удалить '' и вызвать 'f' как' f (g, 42, 'c') '. –
skypjack
Я не уверен, что это * проблема. Возможно, только расширение GCC. – StoryTeller