Подтвердить что ты не робот

Что означает этот код на С++?

Следующий код возвращает размер выделенного стеком массива:

template<typename T, int size>
int siz(T (&) [size])
{
    return size;
}

но я не могу обернуть голову вокруг синтаксиса. Особенно часть T (&) [size]...

4b9b3361

Ответ 1

но я не могу обернуть голову вокруг синтаксиса. Особенно в части 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)))

Ответ 2

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. В этом случае, хотя весь ваш примерный код, о котором заботился, был выведенным размером, и, следовательно, анонимный аргумент избегает предупреждений о неиспользуемых аргументах.

Ответ 3

Это функция, которая становится typename (шаблоны могут использоваться с разными именами) и размер снаружи. Затем он возвращает этот размер.

Функции стека часто используют size, который является целым числом, которое показывает размер размера стека, который вы запрашиваете с помощью этой функции. & проверяет только размер стека T.