Давайте рассмотрим два шаблона функций:
template <typename T> void f(T);
template <typename T> void g(T const&);
И скажем, у нас есть массив:
int a[10];
Что происходит, когда мы вызываем f(a);
?Поскольку мы явно не предоставляем аргумент в шаблон, выводится аргумент, и компилятор пытается выяснить, что T
основано на аргументе.Аргумент имеет тип int[10]
.T
никогда не будет выведен как ссылочный тип, и вы не можете передать массив по значению, поэтому происходит неявное преобразование массива в указатель, и T
выводится как int*
.
Что происходит, когда мы звоним g(a);
?Опять же, вычет аргумента используется, чтобы определить, что такое T
.Параметр относится к типу и ссылается на T
, поэтому T
может быть напрямую выведено в int[10]
и преобразование массива в указатель не происходит.
Обратите внимание, что лучшим решением для определения длины массива является явное требование, чтобы шаблон получил массив:
template <typename T, std::size_t N>
std::size_t array_length(T const (&)[N]) { return N; }