CPP C++ logo

Наверняка многие «плюсовыми» используют макрос, подобный нижеприведенному:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#define countof(array) (sizeof(array)/sizeof(array[0]))
#define countof(array) (sizeof(array)/sizeof(array[0]))
#define countof(array) (sizeof(array)/sizeof(array[0]))

Он хорош до тех пор, пока в качестве array в него не будет передан указатель на array. Компилятор проглотит и ничего не скажет, а результат будет совсем не тот, которого ожидает разработчик.

Благодаря constexpr появившемуся в C++11 есть возможность сделать безопасный countof.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
template <class T, size_t N>
constexpr size_t countof(const T (&)[N]) noexcept {
return N;
}
template <class T, size_t N> constexpr size_t countof(const T (&)[N]) noexcept { return N; }
template <class T, size_t N>
constexpr size_t countof(const T (&)[N]) noexcept {
   return N;
}

Теперь на этапе компиляции произойдет ошибка:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const int values[] = { 42, 76, 16, 11, 31 };
void foo(const int v[])
{
for (size_t i = 0; i < countof(v); ++i) // <-- compilation error!
{
bar(v[i]);
}
}
const int values[] = { 42, 76, 16, 11, 31 }; void foo(const int v[]) { for (size_t i = 0; i < countof(v); ++i) // <-- compilation error! { bar(v[i]); } }
const int values[] = { 42, 76, 16, 11, 31 };
 
void foo(const int v[])
{
   for (size_t i = 0; i < countof(v); ++i) // <-- compilation error!
   {
      bar(v[i]);
   }
}

Версия для C++98 может быть такой:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
template <typename T, size_t N>
char (&CountOfHelper(T(&)[N]))[N];
#define countof(x) sizeof(CountOfHelper(x))
template <typename T, size_t N> char (&CountOfHelper(T(&)[N]))[N]; #define countof(x) sizeof(CountOfHelper(x))
template <typename T, size_t N>
char (&CountOfHelper(T(&)[N]))[N];
#define countof(x) sizeof(CountOfHelper(x))