There are several good reasons to choose.
#include <cstdlib> template<typename T, std::size_t N> constexpr std::size_t ARRAY_COUNT_FUNC(T (&arr)[N]) { return N; }
but not
#define ARRAY_COUNT_MACRO(arr) (sizeof(arr)/sizeof(*arr))
One important difference is that when a pointer (not an array) is passed to ARRAY_COUNT_MACRO , it silently returns a useless answer, but passing the same argument to ARRAY_COUNT_FUNC will result in a compiler error indicating an error.
But a macro has one advantage: its argument is not evaluated.
#include <utility> struct S { int member_array[5]; }; // OK: std::size_t count1 = ARRAY_COUNT_MACRO(std::declval<S&>().member_array); // ERROR: std::declval is odr-used! std::size_t count2 = ARRAY_COUNT_FUNC(std::declval<S&>().member_array);
Is there a different approach with the benefits of both together? I. e., Which causes a compilation error if the argument is not an array and does not use an odr argument.
source share