Волшебные аргументы в шаблонах функций

В следующем коде

#include<iostream>

 template<typename T,size_t N> 
 void cal_size(T (&a)[N])
 { 
     std::cout<<"size of array is: "<<N<<std::endl;
 }

 int main()
 {
     int a[]={1,2,3,4,5,6};
     int b[]={1};

     cal_size(a);
     cal_size(b);
 }

Как ожидалось размер обоих массивы печатается. Но как делает N, автоматически инициализируется к правильному значению размера массива (массивы передаются ссылкой)? Как вышеупомянутая работа кода?

21
задан Prasoon Saurav 5 March 2010 в 05:38
поделиться

3 ответа

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 ++.

32
ответ дан 29 November 2019 в 20:35
поделиться

Это работает, потому что тип a - "массив длины 6 из int", а тип b - "массив длины 1 из int". Компилятор знает это, поэтому он может вызвать правильную функцию. В частности, первый вызов вызывает экземпляр шаблона cal_size<6>(), а второй - cal_size<1>(), поскольку это единственные экземпляры шаблона, которые соответствуют своим аргументам.

Если вы попытаетесь вызвать явный экземпляр шаблона, это сработает только в том случае, если вы правильно указали размер, иначе аргументы не совпадут. Рассмотрим следующее:

cal_size(a);    // ok, compiler figures out implicitly that N=6
cal_size<int, 6>(a); // also ok, same result as above
cal_size<int, 5>(a); // ERROR: a is not of type "array of length 5 of int"
8
ответ дан 29 November 2019 в 20:35
поделиться

когда вы объявляете int a[] = {1,2,3}, это то же самое, что (или будет переписано как) int a[3] = {1,2,3}, поскольку шаблонизированная функция получает аргумент в виде T a[N], то N будет иметь значение 3.

1
ответ дан 29 November 2019 в 20:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: