为啥模板参数推导在 C++ 中不起作用?
Posted
技术标签:
【中文标题】为啥模板参数推导在 C++ 中不起作用?【英文标题】:Why template argument deduction doesn't work in C++?为什么模板参数推导在 C++ 中不起作用? 【发布时间】:2021-12-06 14:16:24 【问题描述】:我对 C++ 中的模板参数推导有疑问。 我不知道为什么下面的示例不起作用。 样本:
#include <iostream>
template<size_t n>
void PrintArray(const int arr[n])
for (int i = 0; i < n; i++)
printf("%d\n", 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])
但是为什么呢?您能否解释一下为什么当数组按值传递时,编译器无法预测第一个样本中的数组大小?
【问题讨论】:
【参考方案1】:这个函数声明
void PrintArray(const int arr[n])
等价于
void PrintArray(const int *arr)
由于编译器将具有数组类型的参数调整为指向数组元素类型的指针。
来自 C++ 14 标准(8.3.5 函数)
5 一个名称可用于多个不同的功能 单一范围;这是函数重载(第 13 条)。全部 函数的声明应在返回中完全一致 类型和参数类型列表。确定函数的类型 使用以下规则。每个参数的类型(包括 函数参数包)由其自身确定 decl-specifier-seq 和声明符。 确定类型后 每个参数,任何类型为“T 数组”或“函数”的参数 返回T”调整为“指向T的指针”或“指向函数的指针” 返回 T,”。 生成参数列表后 类型,任何修改参数类型的*** cv 限定符都是 形成函数类型时删除。结果列表 转换后的参数类型以及是否存在 省略号或函数参数包是函数的 参数类型列表。 [注:此转换不影响 参数的类型。例如,int()(const int p, decltype(p)) 和 int()(int, const int) 是相同的类型。 - 结尾 注意]
所以无法推导出模板参数n。
像这样声明函数
void PrintArray(const int ( &arr )[n])
或者您可以通过显式指定模板参数来调用原始函数,例如
PrintArray<5>(arr);
【讨论】:
以上是关于为啥模板参数推导在 C++ 中不起作用?的主要内容,如果未能解决你的问题,请参考以下文章