【问题标题】: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])

但是为什么呢?您能否解释一下为什么当数组按值传递时,编译器无法预测第一个样本中的数组大小?

【问题讨论】:

    标签: c++ arrays templates pass-by-reference pass-by-value


    【解决方案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);
    

    【讨论】:

      猜你喜欢
      • 2015-10-06
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      • 2021-03-14
      • 2012-02-07
      • 1970-01-01
      • 2017-12-26
      相关资源
      最近更新 更多