Stupid C++ Tricks: A better sizeof_array()
先上代码:
template<typename Ty, size_t Num> char(&CountOfRequireArrayArgumentT(const Ty(&)[Num]))[Num]; #define BX_COUNTOF(_x) sizeof(bx::CountOfRequireArrayArgumentT(_x) )
-------------------------------------------------------------------------------------------------------------------------
一种简单的写法是:(there is always a well-known solution to every human problem — neat, plausible, and wrong)
#define sizeof_array(x) (sizeof(x) / sizeof(x[0]))
但因为这是宏,没有任何类型检查,只要展开后语句合法。
#define BAD_SIZEOF_ARRAY(x) (sizeof(x) / sizeof(x[0])) int main() { int ia[10]; std::vector< double > dv; std::string s; float* fp; std::printf("BAD_SIZEOF_ARRAY(ia): %d ", BAD_SIZEOF_ARRAY(ia)); std::printf("BAD_SIZEOF_ARRAY(dv): %d ", BAD_SIZEOF_ARRAY(dv)); std::printf("BAD_SIZEOF_ARRAY(s): %d ", BAD_SIZEOF_ARRAY(s)); std::printf("BAD_SIZEOF_ARRAY(fp): %d ", BAD_SIZEOF_ARRAY(fp)); }
C++里面Macro functions没有强类型检查,而是允许 duck typing(哈哈 interesting)。
----------------------------------------------------------------------------------------------
为了保证只允许静态数组使用,于是有了上面第一种写法。下面解释一下
1. template< typename T, size_t N > void OnlyTakesArray(T (&)[N]);
一个模板函数签名,接收一个类型为T,长度为N的静态数组引用为参数。没毛病。
1.5:如果你要写成这样:直接返回N,可能就有问题了:
template< typename T, size_t N > size_t sizeof_array(T (&)[N]) { return N; }
一些老的编译器(或者没有inline优化,或者不能通过类似c++11 constexpr等方式告诉编译器这是个编译期常量)会生成一个运行时函数,也就是说编译期不能使用这个N
2. “sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1”
那么 sizeof(char[N]) 就是N了,所以我们要想办法搞个char[N]出来,于是:
template< typename T, size_t N > char (&sizeof_array(T (&)[N]))[N];
char(&xxx())[N] 的意思是,xxx()这个函数会返回一个char[N]的引用。==!
3. “ The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is not evaluated, or a parenthesized type-id.”
意思是我们不需要实现sizeof_array这个函数。good.