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

问题描述 投票:0回答:3

我在文章 PVS-Studio vs Chromium

中看到了这个片段
template <typename T, size_t N>  
char (&ArraySizeHelper(T (&array)[N]))[N];  
#define arraysize(array) (sizeof(ArraySizeHelper(array))) 

我见过其他模板可以做同样的事情,比如 使用模板获取数组的大小和结束地址

我理解这些,但我一直在这方面遇到困难。

c++ templates metaprogramming c++98
3个回答
11
投票

函数模板名为

ArraySizeHelper
,该函数接受一个参数、对
T [N]
的引用,并返回对
char [N]
的引用。

宏将您的对象(假设它是

X obj[M]
)作为参数传递。编译器推断出
T == X
N == M
。所以它声明了一个返回类型为
char (&)[M]
的函数。然后宏用
sizeof
包装这个返回值,所以它实际上是在做
sizeof(char [M])
,即
M

如果给它一个非数组类型(例如

T *
),那么模板参数推断将会失败。

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


8
投票

这不是最好的方法,但既然你问:模板函数

ArraySizeHelper
的返回类型是
char[N]
,其中函数的参数是一个(引用)大小的数组N 类型为
T
。模板参数推导使用匹配的数字 N 实例化该模板,因此
sizeof(char[N])
就是 N,这就是您得到的。

更好的版本可以写如下。 (

constexpr
需要 C++11;如果省略它,这将不是常量表达式。)

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

用途:

int x[20];
array_size(x); // == 20

更新: 如果您使用 C++11,这里是另一个提供 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

如果您使用的是 C++17,还可以使用

std::size
来获取数组的大小。


4
投票

MSDN 上的这篇博客准确地描述了它的工作原理。非常有趣的故事。看看吧。

© www.soinside.com 2019 - 2024. All rights reserved.