为什么 C++ 模板数组长度推导需要像 “f(T (&a)[N]” ?

Why C++ template array length deduction need to be like "f(T (&a)[N]"?

提问人:Immanuel Kant 提问时间:6/28/2022 最后编辑:Vlad from MoscowImmanuel Kant 更新时间:6/28/2022 访问量:195

问:

使用 C++ 模板知道 C 样式数组的长度,我们需要这个:

#include<stdio.h>
template<class T,size_t N>
size_t length(T (&a)[N]){ return N; }
int main() {
    int fd[2];
    printf("%lld\n", length(fd));;
    return 0;
}

它有效,打印.我的问题是关于语法的。2

在 的声明中,为什么参数应该像 一样,而不起作用?length(&a)[N]a[N]

如果我更改为

template<class T,size_t N>
size_t length(T a[N]){ return N; }

GCC会说:

template argument deduction/substitution failed:
couldn't deduce template parameter 'N'

为什么这里需要一个额外的数组标识符和一对大括号,这背后的模板规则/语法规则是什么?&

欣赏详细的解释。

C++ 数组模板 按引用传递值

评论

2赞 Drew Dormann 6/28/2022
使参数成为参考变量。对数组的引用不受 C 样式规则的约束,即作为参数传递的 C 样式数组将衰减为指针。&
1赞 Ted Lyngmo 6/28/2022
不相关:对于 是错误的(或可能是)。用%lldsize_t%zu
0赞 Ted Lyngmo 6/28/2022
更正:肯定是错误的,因为这需要一个有符号的参数。%lld

答:

6赞 Vlad from Moscow 6/28/2022 #1

在此函数声明中

template<class T,size_t N>
size_t length(T a[N]){ return N; }

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

也就是说,这个声明实际上等同于

template<class T,size_t N>
size_t length(T *a){ return N; }

另一方面,在此调用中用作参数表达式的数组

length(fd)

隐式转换为指向其第一个元素的指针。

所以编译器无法推导出模板非类型参数 N 的值。

当参数被声明为引用时,不会发生上述调整和隐式转换。引用用作数组的别名。

请注意,要使用 C 函数输出无符号整数类型的对象,您需要使用转换说明符而不是 .size_tprintfzulld