Поведение этого кода объясняется C ++ 14 [temp.deduct.call]:
Вывод аргументов шаблона из вызова функции
Вывод аргумента шаблона выполняется путем сравнения каждого типа параметра шаблона функции (назовите его P
) с типом соответствующего аргумента вызова (назовите его A
), как описано ниже
, а затем ниже:
Если P
не является ссылочным типом:
- Если
A
является типом массива, тип указателя, созданный стандартным преобразованием массива в указатель (4.2), используется вместо A
для вывода типа;
Для звонка f(array);
у нас есть A
= int[27]
. A
- это тип массива. Таким образом, выведенный тип T
равен int *
, в соответствии с этой последней точкой.
Из квалификатора «Если P
не является ссылочным типом» мы можем видеть, что такого поведения можно было бы избежать, если сделать P
ссылочным типом. Для кода:
template<typename T, size_t N>
void f(T (&x)[N])
символ P
означает T(&)[N]
, который является ссылочным типом; и оказывается, что здесь нет примененных преобразований. T
выводится на int
, с типом x
, равным int(&)[N]
.
Обратите внимание, что это относится только к шаблонам функций, где тип определяется из аргумента. Поведение описывается отдельными частями спецификации для явно предоставленных параметров шаблонов функций и шаблонов классов.