cppreference утверждает следующее
template <class ...T> int f(T*...); // #1
template <class T> int f(const T&); // #2
f((int*)0); // OK: selects #1
// (was ambiguous before DR1395 because deduction failed in both directions)
Если мы следуем DR1395, мы видим
Если A был преобразован из пакета параметров функции, а P не является пакетом параметров, вывод типа завершается ошибкой.Впротивном случае,спомощьюИспользуя полученные типы Р и, вычет затем сделано, как описано в 17.9.2.5 [temp.deduct.type]. Если P является пакетом параметров функции, тип A каждого оставшегося типа параметра шаблона аргумента сравнивается с типом P идентификатора объявления пакета функциональных параметров. Каждое сравнение выводит аргументы шаблона для последующих позиций в пакетах параметров шаблона, расширенных пакетом параметров функции. Аналогично, если A был преобразован из пакета параметров функции, он сравнивается с каждым оставшимся типом параметра шаблона параметра. Если для данного типа вывод выполняется успешно, считается, что тип из шаблона аргумента является по меньшей мере таким же специализированным, как и тип из шаблона параметра.[...]
Если после рассмотрения вышеизложенного шаблон функции F по меньшей мере столь же специализирован, как и шаблон функции G, и наоборот, и если G имеет пакет конечных параметров, для которого F не имеет соответствующего параметра, и если у F нет завершающего Пакет параметров, то F более специализирован, чем G.
Из того, что я могу сделать вывод, это означает, что мы должны сопоставлять каждый отдельный тип, расширенный от T*...
до const T&
и наоборот. В этом случае T*
более специализирован, чем const T&
(T
из U*
завершается успешно, T*
из U
завершается неудачей).
Однако составители не согласны. Кланг считает, что это неоднозначно, а gcc считает, что следует вызвать второе, оба из которых отличаются от cppreference.
Какое правильное поведение?