为什么模板参数推导在C++不起作用?



我在c++中有一个模板参数推导的问题。我不知道为什么下面的样品不能工作。示例:

#include <iostream>
template<size_t n>
void PrintArray(const int arr[n]) {
for (int i = 0; i < n; i++)
printf("%dn", arr[i]);
}
int main() {
int arr[5] = {1, 2, 3, 3, 5};
PrintArray<>(arr);
return 0;
}

编译器打印这个错误:

main.cpp: In function 'int main()':
main.cpp:12:21: error: no matching function for call to 'PrintArray(int [5])'
PrintArray<>(arr);
^
main.cpp:4:6: note: candidate: template<unsigned int n> void PrintArray(const int*)
void PrintArray(const int arr[n]) {
^~~~~~~~~~
main.cpp:4:6: note:   template argument deduction/substitution failed:
main.cpp:12:21: note:   couldn't deduce template parameter 'n'
PrintArray<>(arr);

我发现如果我通过引用传递参数,代码就会正常工作,所以函数签名变成这样:

void PrintArray(const int (&arr)[n])

但是为什么呢?你能解释一下为什么编译器不能预测数组大小在第一个样本,当数组传递值?

此函数声明

void PrintArray(const int arr[n]) {

等价于

void PrintArray(const int *arr) {

由于编译器将具有数组类型的形参调整为指向数组元素类型的指针。

选自c++ 14标准(8.3.5 Functions)

一个名称可以用于一个函数中的多个不同函数单一的范围;这就是函数重载(第13条)。所有函数的声明必须在return和return中完全一致类型和参数类型列表。函数的类型被确定使用以下规则。每个参数的类型(包括函数参数包)是由它自己确定的decl- specific -seq和声明器。在确定类型后每个参数,任何类型为"数组T"或"函数"的参数将"返回T"调整为"指向T的指针"或"指向函数的指针">生成参数列表后类型,任何修改参数类型的顶级cv限定符都是在形成函数类型时删除。的结果列表转换后的参数类型以及是否存在省略号或函数参数包是函数的parameter-type-list。[注:此转换不影响。参数类型。例如,int()(const int p,Decltype (p))和int()(int, const int)是相同的类型。- - -结束注意]

因此不可能推导出模板参数n。

那样声明函数
void PrintArray(const int ( &arr )[n]) {

或者可以通过显式指定模板参数(如

)来调用原始函数
PrintArray<5>(arr);