这个数组大小模板如何工作?

时间:2011-06-16 17:23:40

标签: c++ templates metaprogramming

我遇到了这个片段

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

我理解这些,但我一直遇到这个问题。

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:11)

函数模板名为ArraySizeHelper,用于接受一个参数的函数,对T [N]的引用,并返回对char [N]的引用。

宏传递你的对象(假设它是X obj[M])作为参数。编译器推断出T == XN == 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准确地描述了它的工作原理。非常有趣的故事。看看吧。