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

Как работает эта функция шаблона "размер массива"?

Возможные дубликаты:
Может ли кто-нибудь объяснить этот код шаблона, который дает мне размер массива?
Magic arguments in function templates…

Может кто-нибудь объяснить, как работает этот код? Я знаю, что цель этого кода - получить длину массива, но я не знаю, как работает этот код:

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

Спасибо.

4b9b3361

Ответ 1

Сначала рассмотрим параметр T(&)[size]. Сначала читать декларации изнутри, справа налево, группу скобок: это неназванный параметр, который является ссылкой на массив размера size типа T.

То есть, он принимает ссылку на любой массив, где тип и размер массива являются параметрами шаблона.

Если мы назовем это следующим:

int a[10];
GetArrLength(a);

Компилятор попытается вывести параметры шаблона. Для того чтобы тип параметра соответствовал тому, что вы передаете, T должен быть int и size должен быть 10 (что делает параметр ссылкой на массив из 10 int s).

Затем вы возвращаете этот размер, указывая количество элементов в массиве.


В этом коде есть две проблемы. Во-первых, размеры не могут быть отрицательными, поэтому нет смысла использовать подписанный тип в качестве параметра шаблона и типа возврата. Вместо этого следует использовать неподписанный тип; лучше всего было бы std::size_t:

template<typename T, std::size_t Size>
std::size_t GetArrLength(T(&)[Size]) { return size; }

Во-вторых, результат этой функции не является константным выражением, даже если размер массива. Хотя это прекрасно в большинстве ситуаций, было бы лучше, если бы мы могли получить от него постоянное выражение. То, что вы в конечном итоге с этим решением:

template <std::size_t N>
struct type_of_size
{
    typedef char type[N];
};

template <typename T, std::size_t Size>
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]);

#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray))

Это используется как таковое:

int a[10];
const std::size_t n = sizeof_array(a); // constant-expression!

Он работает по трем вещам: первая - это та же идея, что и выше, что параметры шаблона будут заполнены, что даст вам размер массива.

Вторая часть использует эту информацию для создания типа с определенным размером, поэтому помощник type_of_size. Эта часть не является строго необходимой, но я думаю, что это упрощает чтение кода. A char[N] имеет размер, равный N, всегда, поэтому мы можем злоупотреблять этим, чтобы "хранить" размер массива... в размере самого типа!

Третья часть получает этот размер с помощью sizeof. На самом деле это ничего не оценивает, поэтому нам не нужно определение функции. Он просто говорит: "Если бы вы сделали это... размер был бы...". Размер - наш "сохраненный" размер в массиве char.