Почему следующие два объявления шаблона неоднозначны (так что ни один из них не является более специализированным, чем другой)? Я знаю, что этот вопрос много раз поднимался в Stack Overflow, но обычно люди отвечают, как разрешить неоднозначность, а не почему это произошло.
I.
template <class T> void func(char* buf, T size) {}
II.
template <std::size_t N> void func(char (&buf)[N], std::size_t size) {}
Попытка пройти шаги стандарта C ++ 14 для разрешения частичного упорядочивания шаблонов функций (14.5.6.2):
Для создания преобразованного шаблона для каждого типа, не-типа или параметра шаблона шаблона (включая их пакеты параметров шаблона (14.5.3)) синтезируйте уникальный тип, значение или шаблон класса соответственно и подставляйте его для каждого вхождения этого параметра. в типе функции шаблона.
Тип функции шаблона преобразованной функции I: void func(char*, U1)
, где U1
- некоторый уникальный синтетический тип.
Тип функции шаблона преобразованной функции II: void func(char (&buf)[N1], std::size_t)
, где N1
- некое уникальное синтетическое значение.
Используя тип функции преобразованного шаблона функции, выполните определение типа для другого шаблона, как описано в 14.8.2.4.
Итак, давайте попробуем выполнить вывод типа с одной стороны (используя первый шаблон в качестве аргумента, а второй - в качестве шаблона параметра) и с противоположной стороны.
Дело 1.
Шаблон параметра: template <std::size_t N> void func(char (&buf)[N], std::size_t size)
. Шаблон преобразованного аргумента: void func(char*, U1)
.
Пытаюсь вывести параметры шаблона. «char (&buf)[N]
» не может быть выведено из типа «char*
». U1 также не соответствует типу std::size_t
. Не удалось.
Случай 2.
Шаблон параметра: template <class T> void func(char* buf, T size)
. Шаблон преобразованного аргумента: void func(char (&buf)[N1], std::size_t)
.
Пытаюсь вывести параметры шаблона. Первый аргумент шаблона параметра вообще не тип и совместим с char[]
. T
следует вывести на std::size_t
.
Таким образом, шаблон II должен быть более специализированным и должен быть выбран в следующем коде:
char buf[16];
func(buf, static_cast<std::size_t>(16));
Почему это не так для GCC 5.3 и Clang 4.0?
std::size_t
. В более общем плане я бы добавил, что преобразование массива в указатель является удивительно агрессивным, и в прошлом было сложно выяснить, действительно ли это преобразование влияет на порядок. Однако на SO уже есть несколько таких вопросов. - person Nir Friedman   schedule 23.01.2018P=char *
иA=char [N1]
не будут вычитать. (То есть, если мы проигнорируем сомнительное добавление CWG 1391 к [temp.deduct.partial] p4, которое вызывает собственные проблемы.) - person T.C.   schedule 24.01.2018template<class> void f(int); template<class T> void f(T); f<int>(0);
), и заказывает некоторые вещи, которые, вероятно, должны быть неупорядоченными (template<class T> void f(T, short); template<class T> void f(T*, char); f((char*)0, 0);
) - person T.C.   schedule 26.01.2018