好むいくつかの正当な理由があります
#include <cstdlib>
template<typename T, std::size_t N>
constexpr std::size_t ARRAY_COUNT_FUNC(T (&arr)[N]) { return N; }
それよりも
#define ARRAY_COUNT_MACRO(arr) (sizeof(arr)/sizeof(*arr))
重要な違いの1つは、ポインタ(配列ではない)がに渡されるとARRAY_COUNT_MACRO
、役に立たない答えが黙って返されることですが、同じ引数をに渡すとARRAY_COUNT_FUNC
、間違いを指摘するコンパイラエラーが発生します。
しかし、マクロには1つの利点があります。それは、その引数が評価されていないことです。
#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);
両方の利点を一緒に持つ別のアプローチはありますか?つまり、引数が配列でない場合にコンパイルエラーを引き起こし、その引数をodr-useしないもの。