我遇到了这个片段
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
在本文http://software.intel.com/en-us/articles/pvs-studio-vs-chromium/
中我见过其他模板做同样的事情,比如这个
Use templates to get an array's size and end address
我理解这些,但我一直遇到这个问题。
任何帮助都将不胜感激。
答案 0 :(得分:11)
函数模板名为ArraySizeHelper
,用于接受一个参数的函数,对T [N]
的引用,并返回对char [N]
的引用。
宏传递你的对象(假设它是X obj[M]
)作为参数。编译器推断出T == X
和N == M
。因此它声明了一个返回类型为char (&)[M]
的函数。宏然后用sizeof
包装此返回值,因此它实际上正在sizeof(char [M])
,M
。
如果你给它一个非数组类型(例如T *
),那么模板参数推断就会失败。
正如@Alf在下面指出的那样,这种混合模板 - 宏系统相对于替代模板方法的优势在于它为您提供了编译时常量。
答案 1 :(得分:7)
这不是最好的方法,但是因为你问:模板函数ArraySizeHelper
的返回类型是char[N]
,其中函数的参数是(参考) a)类型T
的大小为N的数组。模板参数推导使用匹配的数字N来实例化此模板,因此sizeof(char[N])
只是N,这就是你得到的。
更好的版本可以编写如下。 (constexpr
需要C ++ 0x;如果省略它,则不会是常量表达式。)
template <typename T, size_t N> constexpr size_t array_size(const T (&)[N]) { return N; }
用法:
int x[20];
array_size(x); // == 20
更新:如果您使用的是C ++ 0x,这是另一个提供constexpr的解决方案,这要归功于decltype:
#include <type_traits>
template <typename T> struct array_traits;
template <typename T, unsigned int N> struct array_traits<T[N]>
{
static const unsigned int size = N;
typedef std::decay<T>::type type;
};
// Usage:
int x[20];
array_traits<decltype(x)>::size; // == 20
答案 2 :(得分:4)
This blog on MSDN准确地描述了它的工作原理。非常有趣的故事。看看吧。