N
не инициализируется ни к чему. Это не переменная. Это не объект. N
- это константа времени компиляции. N
существует только во время компиляции. Значение N
, а также фактическое T
определяется процессом, называемым вычет аргумента шаблона . И T
, и N
выводятся из фактического типа аргумента, который вы передаете в функцию шаблона.
В первом вызове тип аргумента - int[6]
, поэтому компилятор определяет, что T == int
и N == 6
, генерирует для этого отдельную функцию и вызывает ее. Давайте назовем это cal_size_int_6
void cal_size_int_6(int (&a)[6])
{
std::cout << "size of array is: " << 6 << std::endl;
}
Обратите внимание, что в этой функции больше нет T
и N
. Оба были заменены их фактическими выведенными значениями во время компиляции.
В первом вызове тип аргумента - int[1]
, поэтому компилятор определяет, что T == int
и N == 1
, также генерирует отдельную функцию и вызывает ее. Давайте назовем это cal_size_int_1
void cal_size_int_1(int (&a)[1])
{
std::cout << "size of array is: " << 1 << std::endl;
}
То же самое здесь.
Ваш main
по сути переводится в
int main()
{
int a[]={1,2,3,4,5,6};
int b[]={1};
cal_size_int_6(a);
cal_size_int_1(b);
}
Другими словами, ваш шаблон cal_size
порождает две разные функции (так называемые специализации исходного шаблона), каждая из которых имеет различные значения N
(и T
) закодировано в теле. Так работают шаблоны в C ++.