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

Why template argument deduction doesn't work in C++?

我对 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])

但是为什么呢?你能解释一下为什么当数组按值传递时编译器无法预测第一个示例中的数组大小吗?

这个函数声明

void PrintArray(const int arr[n]) {

相当于

void PrintArray(const int *arr) {

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

来自 C++ 14 标准(8.3.5 函数)

5 A single name can be used for several different functions in a single scope; this is function overloading (Clause 13). All declarations for a function shall agree exactly in both the return type and the parametertype-list. The type of a function is determined using the following rules. The type of each parameter (including function parameter packs) is determined from its own decl-specifier-seq and declarator. After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively. After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type. The resulting list of transformed parameter types and the presence or absence of the ellipsis or a function parameter pack is the function’s parameter-type-list. [ Note: This transformation does not affect the types of the parameters. For example, int()(const int p, decltype(p)) and int()(int, const int) are identical types. — end note ]

所以推导模板参数n是不可能的

像这样声明函数

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

或者您可以通过明确指定模板参数来调用原始函数,例如

PrintArray<5>(arr);