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 == X
和N == M
.所以它声明了一个返回类型为的函数char (&)[M]
.然后宏将这个返回值包装起来sizeof
,所以它确实在做sizeof(char [M])
,这是M
.
如果给它一个非数组类型(例如a T *
),则模板参数推断将失败.
正如@Alf在下面指出的那样,这种混合模板 - 宏系统优于替代模板方法的优势在于它为您提供了编译时常量.
这不是最好的方法,但是因为你要问:模板函数的返回类型ArraySizeHelper
是char[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)