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

Bob*_*ond 47 c++ arrays size templates sizeof

可能的重复:
有人可以解释这个给我数组大小的模板代码吗?
函数模板中的魔术参数......

有人可以解释这段代码的工作原理吗 我知道这段代码的目的是获取数组的长度,但我不知道这段代码是如何工作的:

template<typename T, int size>
int GetArrLength(T(&)[size]){return size;}
Run Code Online (Sandbox Code Playgroud)

谢谢.

GMa*_*ckG 58

首先让我们剖析参数T(&)[size].从内到外,从右到左,括号组首先读取声明:它是一个未命名的参数,它是size对类型大小的数组的引用T.

也就是说,它接受对任何数组的引用,其中数组的类型和大小是模板参数.

如果我们这样称呼它:

int a[10];
GetArrLength(a);
Run Code Online (Sandbox Code Playgroud)

编译器将尝试推导出模板参数.要使参数类型与您传递的内容相匹配,T必须intsize必须为10(使参数成为对10 ints 数组的引用).

然后返回该大小,为您提供数组中的元素数.


这段代码有两个"问题".首先,大小不能是负数,因此使用带符号的类型作为模板参数和返回类型是没有意义的.相反,应该使用无符号类型; 最好的是std::size_t:

template<typename T, std::size_t Size>
std::size_t GetArrLength(T(&)[Size]) { return size; }
Run Code Online (Sandbox Code Playgroud)

第二个是这个函数的结果不是常量表达式,即使数组的大小是.虽然在大多数情况下都没问题,但如果我们能从中得到一个常量表达式会更好.这就是你最终得到这个解决方案的地方:

template <std::size_t N>
struct type_of_size
{
    typedef char type[N];
};

template <typename T, std::size_t Size>
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]);

#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray))
Run Code Online (Sandbox Code Playgroud)

这样使用:

int a[10];
const std::size_t n = sizeof_array(a); // constant-expression!
Run Code Online (Sandbox Code Playgroud)

它的工作原理有三个:第一个是与上面相同的想法,模板参数将填充给你数组的大小.

第二部分是使用该信息来制作具有特定大小的类型,因此是type_of_size帮助者.那部分并不是绝对必要的,但我认为它使代码更容易阅读.A char[N]的大小N总是等于,因此我们可以滥用它来"存储"数组的大小...以类型本身的大小!

第三部分是用这个尺码sizeof.它实际上并没有评估任何东西,所以我们不需要函数的定义.它简单地说"如果你这样做......那么大小......".并且大小是我们在char阵列中的"存储"大小.

  • 使用C++ 11的`constexpr`,'return n;' 函数成为编译时常量!`template <typename T,size_t n> constexpr size_t array_size(const T(&)[n]){return n; }` (19认同)
  • T&[size]是一系列参考文献.您想要一个数组的引用. (7认同)
  • 您可以在最后一个版本中跳过锅炉铭牌代码,但会以可读性为代价,但我正在将此作为@Matthew Flaschen和@BobAlmond的练习:)`template <typename T,size_t size> char(&sizeof_array_helper(T(&)) [size]))[size];` - 宏将保持不变. (5认同)