Number of array elements

(or one more reason to love C++).

Problem: how to find out number of elements in a C++ array? The most popular form is probably:

#define RDE_COUNT_OF(arr) (sizeof(arr)/sizeof(arr[0]))
Foo myTab[10];
size_t numElems = RDE_COUNT_OF(myTab);
assert(numElems == 10); 
It’s being widely used, however most people do not realize the potential danger with this small piece of code.

Imagine that one day we decide to change our static array to dynamically allocated block of memory:

Foo* myTab = new Foo[numNeededFoos];
size_t numElems = RDE_COUNT_OF(myTab); // Huh?!?

Code compiles without single complaint, but of course it’s wrong in majority of cases. Let’s try to create version that wont accept pointers. There’s obvious solution that circulated around for a while, but compilers didnt like it so much:

template size_t CountOf(const T (&)[N])
    return N;
Todays compilers seem to grasp it without problems. It wont accept pointers, so this one has been solved. However, it’s still not perfect, because array size is known at run-time, not during compilation. This means, it wont work in the following scenario:
Foo myTab[5];
Foo myTab2[CountOf(myTab)];
What we need is compile-time solution that will only accept arrays of known sizes. In my experience the best tool in such cases is examining return value of function using sizeof operator. Let’s try:
template char (&ArrayCountObj;(const T (&)[N]))[N];
#define RDE_ARRAY_COUNT(arr)    (sizeof(rde::ArrayCountObj(arr)))

Voila! Now try to find out how does it work :) Solution in the next note.

Old comments

Kalms 2008-04-14 05:50:16

Tricky! Thanks for the tip.

bart 2009-01-29 09:50:04

There’s nothing wrong with plain old define. If anyone uses it on anything else than a const table it’s their own goddamn fault :)