Почему следующие два объявления шаблона неоднозначны (так что ни один из них не является более специализированным, чем другой)? Я знаю, что этот вопрос неоднократно поднимался на 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) {}
Попытка выполнить шаги стандарта С++ 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?