Counting Array Elements at Compile-Time
by Ivan J. Johnson

Listing One

// public interface
#define COUNTOF(x)  (                                               \
  0 * sizeof( reinterpret_cast<const ::Bad_arg_to_COUNTOF*>(x) ) +  \
  0 * sizeof( ::Bad_arg_to_COUNTOF::check_type((x), &(x))      ) +  \
  sizeof(x) / sizeof((x)[0])  )                                     
// implementation details
class Bad_arg_to_COUNTOF
{
public:
   class Is_pointer;  // intentionally incomplete type
   class Is_array {};  
   template<typename T>
   static Is_pointer check_type(const T*, const T* const*);
   static Is_array check_type(const void*, const void*);
};

Listing Two

void test_addition_operators()
{
   struct Test_case { const char *a, *b, *sum; };
   Test_case cases[] =
   {
      //  a      b       sum
      { "abc", "xyz", "abcxyz" },
      { "abc",    "",    "abc" },
      {    "", "xyz",    "xyz" },
      {    "",    "",       "" }
   };
   for ( int i = 0 ; i != COUNTOF(cases) ; ++i )
   {
      Test_case& tc = cases[i];
      xstring a(tc.a), b(tc.b), sum(tc.sum);
      ASSERT(    a +    b == sum );
      ASSERT(    a + tc.b == sum );
      ASSERT( tc.a +    b == sum );
      a += b;  // operator+=(const xstring&)
      ASSERT( a == sum );
      a = tc.a;
      a += tc.b;  // operator+=(const char*)
      ASSERT( a == sum );
   }
}


Listing Three

// in Color.h
enum Color
{
   red, blue, green,
};
// in Color.cpp
const char* color_names[] = { "red", "blue", "green" };
const char* get_name(Color c)
{
   return color_names[c];
}


Listing Four

// in Color.h
enum Color
{
   red, blue, green,
   last_color  // one-past-the-end value; must be last
};
// in Color.cpp
const char* color_names[] =
   { "red", "blue", "green", "invalid color" };
const char* get_name(Color c)
{
   return color_names[c];
}
COMPILE_TIME_ASSERT( COUNTOF(color_names) == last_color + 1 );


Listing Five

// returns the number of elements in the passed array
template<typename T, int N>
inline int countof(const T(&)[N])
{
   return N;
}
// a struct defined such that sizeof(Size<N>::Type) == N
template<int N>
struct Size
{
     typedef char Type[N];
};
// returns an object whose size is the number of elements in the passed array
template<typename T, int N>
typename Size<N>::Type& count(const T(&array)[N]);


2


