Не является `void f (A <0>, tuple <T *...>)` более специализированным, чем `void f (A <I>, tuple <T *...>)`?
#include <tuple>
template<int I>
struct A {};
template<int I, typename... T>
void f(A<I>, std::tuple<T *...>) {}
template<typename... T>
void f(A<0>, std::tuple<T *...>) {}
int main()
{
f(A<0>{}, std::tuple<char*, int*, float*>{});
}
Не вторая ли перегрузка f
более специализированная? g++ 4.9.2 говорит, что вызов неоднозначен, clang 3.6.0 принимает его. Какой компилятор прав?
Интересно, что если вы меняете std::tuple<T *...>
на std::tuple<T...>
, g++ отлично справляется с этим, чего я не понимаю.
Ответы
Ответ 1
В соответствии с действующими правилами вторая перегрузка является более специализированной. Некоторая специализация A<@>
с синтезированным значением @
не может быть сопоставлена с A<0>
, но A<0>
может быть сопоставлена с A<I>
(с I=0
). Эта первая асимметрия пары является решающей. Используете ли вы T
или T*
, поскольку шаблон во втором параметре не имеет значения, так как вычет преуспевает в обоих направлениях для этой пары.
Ошибка все еще сохраняется в багажнике и сообщается @Barry как 67228.