Как работает шаблон размера массива?
Я нашел этот фрагмент
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
в этой статье http://software.intel.com/en-us/articles/pvs-studio-vs-chromium/
Я видел другие шаблоны, чтобы сделать то же самое, как этот
Используйте шаблоны, чтобы получить размер и конечный адрес массива
и я это понимаю, но у меня возникли трудности с этим.
Любая помощь будет оценена.
Ответы
Ответ 1
Шаблон функции имеет имя ArraySizeHelper
, для функции, которая принимает один аргумент, ссылку на T [N]
и возвращает ссылку на char [N]
.
В качестве аргумента макрос передает ваш объект (допустим, он X obj[M]
). Компилятор сообщает, что T == X
и N == M
. Таким образом, он объявляет функцию с типом возврата char (&)[M]
. Затем макрос обертывает это возвращаемое значение с помощью sizeof
, поэтому он действительно делает sizeof(char [M])
, который равен M
.
Если вы даете ему тип без массива (например, a T *
), то вывод параметра шаблона не будет выполнен.
Как показано ниже @Alf, преимущество этой гибридной матрицы-макросистемы над альтернативным подходом только шаблона заключается в том, что это дает вам константу времени компиляции.
Ответ 2
Это не самый приятный способ сделать это, но так как вы спрашиваете: тип возврата функции шаблона ArraySizeHelper
равен char[N]
, где аргумент функции является массивом (ссылкой на) размера N типа T
. Вычисление аргумента шаблона создает этот шаблон с совпадающим числом N, поэтому sizeof(char[N])
- это просто N, что вы получаете.
Более приятная версия может быть написана следующим образом. (Вам нужно С++ 0x для constexpr
; если вы его опустите, это не будет постоянным выражением.)
template <typename T, size_t N> constexpr size_t array_size(const T (&)[N]) { return N; }
Использование:
int x[20];
array_size(x); // == 20
Обновление: Если вы находитесь в С++ 0x, вот еще одно решение, которое дает constexpr, благодаря decltype:
#include <type_traits>
template <typename T> struct array_traits;
template <typename T, unsigned int N> struct array_traits<T[N]>
{
static const unsigned int size = N;
typedef std::decay<T>::type type;
};
// Usage:
int x[20];
array_traits<decltype(x)>::size; // == 20
Ответ 3
Этот блог в MSDN точно описывает, как он работает. Очень интересная история. Взгляните на это.