Обычный подход к подсчету элемента массива в C выглядит примерно так:
#define COUNTOF(arr) (sizeof(arr) / sizeof(arr[0]))
Это приводит к выражению интегральной константы, что тоже очень приятно.
Проблема в том, что она не безопасна для типов: int* i; COUNTOF(i); /* compiles :( */
. На практике это должно возникать редко, но для правильности было бы неплохо сделать этот тип безопасности.
В С++ 03 это легко (и в С++ 11 это еще проще, оставлено как упражнение для читателя):
template <typename T, std::size_t N>
char (&countof_detail(T (&)[N]))[N]; // not defined
#define COUNTOF(arr) (sizeof(countof_detail(arr)))
Это использует вывод шаблона, чтобы получить N
, размер массива, а затем кодирует его как размер типа.
Но в C мы не получаем эту функцию языка. Это небольшая рамка, которую я сделал:
// if `condition` evaluates to 0, fails to compile; otherwise results in `value`
#define STATIC_ASSERT_EXPR(condition, value) \
(sizeof(char[(condition) ? 1 : -1]), (value))
// usual type-unsafe method
#define COUNTOF_DETAIL(arr) (sizeof(arr) / sizeof(arr[0]))
// new method:
#define COUNTOF(arr) \
STATIC_ASSERT_EXPR(/* ??? */, \
COUNTOF_DETAIL(arr)) \
Что я могу добавить в /* ??? */
, чтобы получить желаемое поведение? Или это невозможно?
Я бы предпочел, чтобы ответы работали в MSVC (т.е. C89), но ради любопытства любой конкретный ответ будет делать.