template<typename T, size_t n>
size_t array_size(const T (&)[n])
{
return n;
}
我不明白的是这个模板函数的参数。当我将数组传递到该函数时,会发生什么使得
n
成为数组元素的数量?首先,您需要了解尝试从数组中获取值可能会给您一个指向其第一个元素的指针:
int a[] = {1, 2, 3};
int *ap = a; // a pointer, size is lost
int (&ar)[3] = a; // a reference to the array, size is not lost
引用是使用其精确类型或基类类型来引用对象。关键在于模板通过引用接受数组。在C++中不存在将数组(而不是对它们的引用)作为参数的情况。如果您给定一个数组类型的参数,它将成为指针。因此,当我们想要知道传递的数组的大小时,使用引用是必要的。大小和元素类型会自动推导,这通常适用于函数模板。以下是模板示例:
template<typename T, size_t n>
size_t array_size(const T (&)[n]) {
return n;
}
使用之前定义的数组a
调用将隐式实例化以下函数:
size_t array_size(const int (&)[3]) {
return 3;
}
这可以像这样使用:
size_t size_of_a = array_size(a);
我之前想出了一种变化,可以在编译时确定一个值。它不会直接返回该值,而是根据n
给模板赋予一个返回类型。
[编辑:事实证明,有人已经在此处提出了同样的想法]
template<typename T, size_t n>
char (& array_size(const T (&)[n]) )[n];
size_t size_of_a = sizeof(array_size(a));
因为一个拥有n
个元素的char
数组具有n
的大小,这也将给出给定数组中元素的数量。在编译时,所以你可以这样做:
int havingSameSize[sizeof(array_size(a))];
由于该函数从未被调用,因此不需要定义,因此它没有主体。希望我能够澄清一点。
从这个角度来看,假设你有一堆函数:
// Note that you don't need to name the array, since you don't
// actually reference the parameter at all.
size_t array_size(const int (&)[1])
{
return 1;
}
size_t array_size(const int (&)[2])
{
return 2;
}
size_t array_size(const int (&)[3])
{
return 3;
}
// etc...
int a[2];
array_size(a);
template <int n>
size_t array_size(const int (&)[n])
{
return n;
}
template <typename T, int n>
size_t array_size(const T (&)[n])
{
return n;
}
完成了。
编辑: 关于 (&)
的说明
括号是需要的,用来区分int引用数组(不合法)和整数数组的引用(您想要的内容)。由于 []
的优先级高于 &
,因此如果您有以下声明:
const int &a[1];
&
,你需要使用括号来强制改变优先级:const int (&a)[1];
现在你有一个整型数组的常量引用,只包含一个元素。在函数参数列表中,如果你不使用某个参数,可以省略它的名称,但要保留括号:
size_t array_size(const int (&)[1])
数组不会发生任何事情。它是一个未使用的参数,用于解决模板函数签名。
它也不能用作模板参数,但这是一个单独的细节。
#include <iostream>
namespace
{
template <size_t V>
struct helper
{
enum
{
value = V
};
};
template<typename T, size_t Size>
auto get_size(T(&)[Size]) -> helper < Size >
{
return helper < Size >() ;
}
template<typename T>
struct get_value
{
enum
{
value = T::value
};
};
}
int main()
{
std::cout << get_value<decltype(get_size("Foo bar baz"))>::value;
}
constexpr
,函数return n;
可以成为编译时常量!template <typename T, size_t n> constexpr size_t array_size(const T (&)[n]) { return n; }
该函数可以计算数组的大小。 - legends2k