mikejsavage.co.uk • About • Archive • RSS • Thanks for blocking ads! Blocking ads owns: AdGuard for Safari / uBlock Origin for everything else
Lots of C/C++ codebases have a macro for finding the number of elements
in a fixed size array. It's usually defined as #define ARRAY_COUNT( a )
( sizeof( a ) / sizeof( ( a )[ 0 ] ) )
, which is great:
int asdf[ 4 ]; // ARRAY_COUNT( asdf ) == 4
until someone comes along and decides that asdf
needs to be
dynamically sized and changes it to be a pointer instead:
int * asdf; // ARRAY_COUNT( asdf ) == sizeof( int * ) / sizeof( int ) != 4
Now every piece of code that uses ARRAY_COUNT( asdf )
is broken, which
is annoying by itself, but that still looks totally fine to the compiler
and it's not even going to warn you about it.
Well you can fix it by doing this:
template< typename T, size_t N >
constexpr size_t ARRAY_COUNT( const T ( &arr )[ N ] ) {
return N;
}
which correctly explodes when you pass it a pointer:
a.cc: In function ‘int main()’:
a.cc:9:27: error: no matching function for call to ‘ARRAY_COUNT(int*&)’
return ARRAY_COUNT( asdf );
^
a.cc:3:18: note: candidate: template<class T, long unsigned int N> constexpr size_t ARRAY_COUNT(const
T (&)[N])
constexpr size_t ARRAY_COUNT( const T ( &arr )[ N ] ) {
^~~~~~~~~~~
a.cc:3:18: note: template argument deduction/substitution failed:
a.cc:9:27: note: mismatched types ‘const T [N]’ and ‘int*’
return ARRAY_COUNT( asdf );