Что касается этот вопрос, который действительно имеет то же название, но для которого я нашел ответ в стандарте. Я продолжил копать тему и наконец нашел пример кода, на который этот ответ не распространяется.
Давайте рассмотрим этот кусок кода:
template<class T> void func(T* buf); //template I
template<size_t N> void func(char (&buf) [N]); //template II
void g(char (&buf)[3])
{
func(buf) //Error: ambiguous function call (Clang, GCC, ICC, MSVC)
}
Согласно правилам частичного заказа в [Temp.func.order] а также [Temp.deduct.partial], шаблон II должен быть более специализированным, чем шаблон я если кто-то интерпретировал эти правила посредством выполнения этого фрагмента кода:
template <class T> void func1(T* buf) {}
template <std::size_t N> void func2(char (&buf)[N]) {}
struct invented_T{};
constexpr std::size_t invented_N=42;
void is_template_I_more_specialized(invented_T* buf)
{
func2(buf);
//DO NOT COMPILE
// => template I is not more specialized than func2
}
void is_template_II_more_specialized(char (&buf)[invented_N])
{
func1(buf);
//DO COMPILE
// => template II is more specialized than func1
}
Итак, согласно этой интерпретации, шаблон II должно быть более специализированный. Почему бы это не так?
По номеру указано в комментарии, причина в том, что тип T*
не может быть выведено из типа char (&buf)[invented_N]
,
В is_template_II_more_specialized
применяется дополнительное преобразование массива в указатель в соответствии с [Temp.deduct.call] /2.1:
Если P не ссылочный тип:
Если A является типом массива, тип указателя, полученный стандартным преобразованием массива в указатель, используется вместо A для вывода типа; иначе,
…
Это правило применяется только для вывода аргументов шаблона из вызова функции. Для вывода аргументов шаблона во время частичного заказа, такое обращение не применяется.
Преобразования, которые могут применяться во время частичного упорядочения, описаны в [temp.deduct.partial] /5,6,7.
Других решений пока нет …