C++ 这个数组大小模板是如何工作的?

C++ 这个数组大小模板是如何工作的?,c++,templates,metaprogramming,C++,Templates,Metaprogramming,我偶然发现了这个片段 template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N]; #define arraysize(array) (sizeof(ArraySizeHelper(array))) 模板 char(&ArraySizeHelper(T(&array)[N]))[N]; #定义arraysize(数组)(sizeof(ArraySizeHelper(数组

我偶然发现了这个片段

template <typename T, size_t N>  
char (&ArraySizeHelper(T (&array)[N]))[N];  
#define arraysize(array) (sizeof(ArraySizeHelper(array))) 
模板
char(&ArraySizeHelper(T(&array)[N]))[N];
#定义arraysize(数组)(sizeof(ArraySizeHelper(数组)))
本文

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

我理解这些,但我一直很难理解这一点


任何帮助都将不胜感激。

这并不是最好的方法,但因为您在问:模板函数
ArraySizeHelper
的返回类型是
char[N]
,其中函数的参数是
t
类型的大小为N的数组(引用)。模板参数演绎使用匹配的数字N实例化此模板,因此
sizeof(char[N])
仅为N,这就是您得到的结果

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


更新:如果您使用的是C++0x,下面是另一个解决方案,它提供了一个constepr,这多亏了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
#包括
模板结构数组;
模板结构数组
{
静态常量无符号整数大小=N;
typedef std::decation::type type;
};
//用法:
int x[20];
数组特征::大小;//==20

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

宏将对象(假设它是
xobj[M]
)作为参数传递。编译器推断出
T==X
N==M
。因此,它声明了一个返回类型为
char(&)[M]
的函数。宏然后用
sizeof
包装这个返回值,因此它实际上是在执行
sizeof(char[M])
,即
M

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


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

准确地描述了它的工作原理。非常有趣的故事。看一看。

你有什么特别的困难?在工作中有很多不同的C++元素。另请参见下面的解释:(这不是被骗者,我现在懒得搜索它)。链接到被骗者或它没有发生:)我也找不到被骗者,否则我就不会发布了。而真正的问题是为什么不使用
std::extent
而不是这个丑陋的宏呢?我只想补充一点,目的可能是为了将数组大小作为编译时常量(这反过来可以用来指定原始数组的大小)。我记得是一个俄罗斯人首先提出了这种变异。不幸的是,我记不起名字了。所以,我认为函数是声明的,但没有定义?语法对我来说很难解析。@Alf这是2004年,很早:谢谢,我想是返回char(&)[M]的语法让我感到困惑。C/C++数组语法太糟糕了。@Gene Bushuyev:基本上,你可以在任何遵循98标准的编译器中使用这段代码,但除非编译器实现C++0x功能,否则你不能使用你的方法(至少是
decltype
extent
类型特征。出于好奇,你觉得最好的方法是什么?@Jalf:Updated。没有编译器宏!问题是它不是constexpr,不像宏。@DeadMG:True。我们能不能用一种不需要宏的方式来包装它?更重要的是,不需要计算不同的汇编程序输出?只需将
constepr
放在第一个函数模板之前,在C++0x中,
array\u size(x)
也将是一个常量表达式。
int x[20];
array_size(x); // == 20
#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