Магические аргументы в шаблонах функций
В следующем коде
#include template 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 автоматически получает инициализацию до правильного значения размера массива (массивы передаются по ссылке)? Как работает вышеуказанный код?
- Когда использовать std :: forward для пересылки аргументов?
- Можете ли вы создавать пользовательские операторы на C ++?
- C ++ вызывает явный конструктор шаблонов
- Как включить под-просмотр в шаблонах Blade?
- Как изменить шаблоны Visual Studio для нового classа / интерфейса C #?
- Аргументы шаблона по умолчанию для шаблонов функций
- Как создать пользовательские шаблоны редактора / отображения в ASP.NET MVC 3?
- Расширение шаблона шаблонов Variadic
- C ++ Template Metaprogramming - Можно ли выводить сгенерированный код?
- Определите, является ли тип контейнером STL во время компиляции
- Передача строкового литерала в качестве параметра в class шаблонов C ++
- Можно ли создавать стандартные шаблоны контейнеров с неполными типами?
- Как создать функцию шаблона внутри classа? (C ++)
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
две разные функции (так называемые специализации исходного шаблона), каждая из которых имеет cal_size
N
(и T
) в теле. Вот как работают шаблоны на C ++.
Он работает, потому что тип 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(a); // also ok, same result as above cal_size(a); // ERROR: a is not of type "array of length 5 of int"
когда вы объявляете int a [] = {1,2,3}, это то же самое, что (или будет переписано как) int a [3] = {1,2,3}, поскольку шаблонная функция получает аргумент в форме T a [N], то N будет иметь значение 3.