Следующий код возвращает размер выделенного стеком массива:
template<typename T, int size>
int siz(T (&) [size])
{
return size;
}
но я не могу обернуть голову вокруг синтаксиса.
Особенно часть T (&) [size]
...
Следующий код возвращает размер выделенного стеком массива:
template<typename T, int size>
int siz(T (&) [size])
{
return size;
}
но я не могу обернуть голову вокруг синтаксиса.
Особенно часть T (&) [size]
...
но я не могу обернуть голову вокруг синтаксиса. Особенно в части
T (&) [size]
...
Эта часть является ссылкой на массив. Существует "право-левое правило" для расшифровки любых C и С++ деклараций.
Поскольку шаблоны функций выводят типы аргументов шаблона из аргументов функции, которые предоставляет этот шаблон функции, выведите количество элементов и элементов массива и верните счет.
Функции не могут принимать типы массивов по значению, а только указателем или ссылкой. Ссылка используется, чтобы избежать неявного преобразования массива в указатель на его первый элемент (иначе, разложение массива):
void foo(int*);
int x[10];
int* p = x; // array decay
foo(x); // array decay again
Распад массива разрушает исходный тип массива и, следовательно, его размер теряется.
Обратите внимание, что поскольку это вызов функции в С++ 03, возвращаемое значение не является константой времени компиляции (т.е. возвращаемое значение не может использоваться как аргумент шаблона). В С++ 11 функция может быть помечена constexpr
, чтобы вернуть константу времени компиляции:
template<typename T, size_t size>
constexpr size_t siz(T(&)[size]) { return size; }
Чтобы получить элемент массива как константу времени компиляции в С++ 03, можно использовать несколько другую форму:
template<class T, size_t size>
char(&siz(T(&)[size]))[size]; // no definition required
int main()
{
int x[10];
cout << sizeof siz(x) << '\n';
double y[sizeof siz(x)]; // use as a compile time constant 10
}
В приведенном выше примере объявляется шаблон функции с тем же аргументом reference-to-a-array, но с типом возвращаемого значения char(&)[size]
(здесь можно оценить "правое правое правило" ). Обратите внимание, что вызов функции никогда не происходит во время выполнения, поэтому определение шаблона функции siz
не требуется. sizeof siz(x)
в основном говорит: "Каким будет размер возвращаемого значения, если siz(x)
были вызваны".
Старый способ C/С++ для получения количества элементов массива как постоянной времени компиляции:
#define SIZ(arr) (sizeof(arr) / sizeof(*(arr)))
T (&) [size]
- это ссылка на массив. Это должно быть ссылкой, потому что следующая программа не является законной:
#include <iostream>
int sz(int *) { std::cout << "wtf?" << std::endl; return 0; }
int sz(int [4]) { std::cout << "4" << std::endl; return 0; }
int main() {
int test[4];
sz(test);
}
Эта программа не скомпилируется с помощью:
test.cc: In function ‘int sz(int*)’:
test.cc:6:5: error: redefinition of ‘int sz(int*)’
test.cc:3:5: error: ‘int sz(int*)’ previously defined here
потому что int sz(int [4])
идентичен int sz(int *)
.
Скобки необходимы для устранения двусмысленности здесь, потому что T& [size]
выглядит как массив ссылок, который в противном случае является незаконным.
Обычно, если параметр не был анонимным, вы должны написать:
template<typename T, int size>
int sz(T (&arr) [size])
Чтобы дать массиву имя arr
. В этом случае, хотя весь ваш примерный код, о котором заботился, был выведенным размером, и, следовательно, анонимный аргумент избегает предупреждений о неиспользуемых аргументах.
Это функция, которая становится typename (шаблоны могут использоваться с разными именами) и размер снаружи. Затем он возвращает этот размер.
Функции стека часто используют size
, который является целым числом, которое показывает размер размера стека, который вы запрашиваете с помощью этой функции. &
проверяет только размер стека T.