Волшебные аргументы в шаблонах функций - PullRequest
21 голосов
/ 05 марта 2010

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

#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 автоматически инициализируется с правильным значением размера массива (массивы передаются по ссылке)? Как работает приведенный выше код?

Ответы [ 3 ]

32 голосов
/ 05 марта 2010

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 порождает две разные функции (так называемые специализации исходного шаблона), каждая из которых имеет различные значения NT) закодировано в теле. Так работают шаблоны в C ++.

8 голосов
/ 05 марта 2010

Это работает, потому что тип 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"
1 голос
/ 05 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...