Ответ 1
Это CWG1395, для которого дефект разрешение недавно проголосовал за проект стандарта С++ 17. В [temp.deduct.partial] добавлено следующее:
... [if] функциональный шаблон
F
по меньшей мере такой же специализированный, как шаблон функцииG
и наоборот, и еслиG
имеет завершающий пакет параметров, для которогоF
не имеет соответствующего параметр, и еслиF
не имеет завершающего пакета параметров, тоF
более специализирован, чемG
.
В стандарте нет явного определения того, что это означает, "trailing parameter pack", но, судя по существующим контекстам, в которых этот термин используется, он ссылается на пакет параметров шаблона, который отображается как самый правый параметр в параметре шаблона список:
template<class T, class... U> struct X;
// ^^^^^^^^^^
Или пакет функций, который отображается как самый правый параметр в списке параметров функции:
template<class T, class... U> void y(T, U...);
// ^^^^
В текущем черновике все еще содержится этот устаревший пример в [temp.deduct.type]:
template<class T, class... U> void f(T, U...);
template<class T> void f(T);
f(&i); // error: ambiguous
Этот стандартный отчет о дефектах существует уже несколько лет, и GCC и Clang реализовали его разрешения. Они оба согласны с тем, что приведенный выше пример является действительным вызовом второй перегрузки F
.
Если GCC и Clang не согласны в области разрешения дефекта. Это понятно, поскольку он был недавно обновлен, чтобы включить предлагаемую стандартную формулировку. В вашем примере пакет не разложен в список параметров функции, а в список аргументов шаблона типа параметра функции:
template<class T, class... U> void g(tuple<T, U...>);
template<class T> void g(tuple<T>);
g(tuple<int>{});
GCC рассматривает это как действительный вызов второй перегрузки G
; Кланг рассматривает это как неоднозначное. Правильность Clang может зависеть от того, подразумевается ли "trailing parameter pack" включать трейлинг-пакеты параметров шаблона или только завершающие пакеты параметров функции.
Обратите внимание, что оба компилятора согласны с тем, что C<int>
относится ко второй частичной специализации шаблона класса C
в следующем примере:
template<class...> struct C;
template<class T, class... U> struct C<T, U...> {};
template<class T> struct C<T> {};
Это похоже на несогласованность в Clang, поскольку стандартные правила для частичного упорядочения специализированных шаблонов классов определяются в части частичного упорядочения шаблонов функций. См. CWG1432.