有人可以解释这个模板代码,给我一个数组的大小?

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; } 

调用我们以前定义的数组将会隐式地实例化下面的函数:

 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]; 

你说如果数组有n元素,返回类型是一个大小为n ,元素类型为char的数组的引用。 现在,你可以得到一个编译时确定的传递数组的大小:

 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; } 

编译器将尝试实例化与您调用的任何参数相匹配的array_size版本。 所以,如果你用一个10个整数的数组来调用它,它将实例化n = 10的array_size。

接下来,只是模式化的类型,所以你可以调用它不仅仅是int数组:

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

你完成了。

编辑 :关于(&)

圆括号需要围绕&来区分int引用数组(非法)和引用int数组(引用)。 由于[]的优先级高于& ,如果您有声明:

 const int &a[1]; 

由于运算符的优先级,你最终会得到一个int元素的常量引用数组。 如果您希望首先应用& ,则需要用圆括号强制:

 const int (&a)[1]; 

现在你有一个int的一个元素数组的const引用。 在函数参数列表中,如果不使用它,则不需要指定参数的名称,因此可以删除名称,但保留小括号:

 size_t array_size(const int (&)[1]) 

阵列没有任何反应。 这是一个未使用的参数,用于解析模板函数的签名。

它也不能被用作模板参数,但这是一个单独的尼特。

对于没有“constexpr”的我们来说,有一点奇怪的方法来得到编译时const的结果:

 #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; }