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

Big*_*ich 16 c++ templates metaprogramming

我遇到了这个片段

template <typename T, size_t N>  
char (&ArraySizeHelper(T (&array)[N]))[N];  
#define arraysize(array) (sizeof(ArraySizeHelper(array))) 
Run Code Online (Sandbox Code Playgroud)

在这篇文章http://software.intel.com/en-us/articles/pvs-studio-vs-chromium/

我见过其他模板做同样的事情,比如这个

使用模板获取数组的大小和结束地址

我理解这些,但我一直遇到这个困难.

任何帮助,将不胜感激.

Oli*_*rth 11

函数模板被命名ArraySizeHelper为一个带有一个参数的函数,一个对a的引用T [N],并返回对a的引用char [N].

宏将你的对象(让我们说它的X obj[M])作为参数传递.编译器推断出T == XN == M.所以它声明了一个返回类型为的函数char (&)[M].然后宏将这个返回值包装起来sizeof,所以它确实在做sizeof(char [M]),这是M.

如果给它一个非数组类型(例如a T *),则模板参数推断将失败.

正如@Alf在下面指出的那样,这种混合模板 - 宏系统优于替代模板方法的优势在于它为您提供了编译时常量.


Ker*_* SB 7

这不是最好的方法,但是因为你要问:模板函数的返回类型ArraySizeHelperchar[N],函数的参数是(引用)大小为N的数组T.模板参数推导用匹配的数字N实例化该模板,因此sizeof(char[N])只有N,这就是你得到的.

一个更好的版本可以编写如下.(你需要C++ 0x constexpr;如果你省略它,这将不是一个常量表达式.)

template <typename T, size_t N> constexpr size_t array_size(const T (&)[N]) { return N; }
Run Code Online (Sandbox Code Playgroud)

用法:

int x[20];
array_size(x); // == 20
Run Code Online (Sandbox Code Playgroud)

更新:如果你在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
Run Code Online (Sandbox Code Playgroud)

  • 出于好奇,你觉得最好的做法是什么? (2认同)