3 回答
TA贡献1783条经验 获得超4个赞
首先让我们剖析参数T(&)[size]。首先从内到外,从右到左,从括号组中读取声明:这是一个未命名的参数,是size对type类型的数组的引用T。
也就是说,它接受对任何数组的引用,其中数组的类型和大小是模板参数。
如果我们这样称呼它:
int a[10];
GetArrLength(a);
编译器将尝试推断模板参数。为了使参数类型与您要传递的参数相匹配,T必须为int并且size必须为10(使参数成为对10 ints 数组的引用)。
然后,您返回该大小,从而获得数组中元素的数量。
此代码有两个“问题”。首先,大小不能为负,因此使用带符号类型作为模板参数和返回类型没有意义。而是应使用无符号类型。最好是std::size_t:
template<typename T, std::size_t Size>
std::size_t GetArrLength(T(&)[Size]) { return size; }
第二个问题是,即使数组的大小是多少,此函数的结果也不是常量表达式。虽然在大多数情况下都可以,但是如果我们可以从中获得一个常量表达式,那就更好了。那就是您得到此解决方案的地方:
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))
这样使用:
int a[10];
const std::size_t n = sizeof_array(a); // constant-expression!
它通过三件事起作用:第一是与上面相同的想法,模板参数将被填充以提供数组的大小。
第二部分是使用该信息来创建具有特定大小的类型,从而成为一个type_of_size辅助对象。该部分不是严格必需的,但我认为它使代码更易于阅读。A char[N]的大小N始终等于,因此我们可以滥用它来“存储”数组的大小……以类型本身的大小!
第三部分是使用来获得该大小sizeof。它实际上不评估任何东西,因此我们不需要为函数定义。它只是说:“如果要这样做,大小将是……”。大小是char数组中“存储”的大小。
TA贡献1806条经验 获得超5个赞
您可以牺牲可读性来跳过最后一个版本中的样板代码,但是我将其写为@Matthew Flaschen和@BobAlmond的练习:) template <typename T, size_t size> char (&sizeof_array_helper( T (&)[size]))[size];-宏将保留原样。
TA贡献2065条经验 获得超14个赞
使用C ++ 11时constexpr
,“ return n;” 函数成为编译时间常数!template <typename T, size_t n> constexpr size_t array_size(const T (&)[n]) { return n; }
- 3 回答
- 0 关注
- 512 浏览
添加回答
举报