【发布时间】:2021-04-13 14:42:24
【问题描述】:
鉴于下面的两个程序——除了模板函数len()的定义之外完全相同:
// ================================
// a.cc
// ================================
#include <iostream>
template<class T, std::size_t n>
std::size_t len(T (&v)[n]) { return n; }
int main()
{
int arr[] = { 1,2,3 };
std::cout << len(arr) << std::endl;
}
// ================================
// b.cc
// ================================
#include <iostream>
template<class T, std::size_t n>
std::size_t len(T v[n]) { return n; }
int main()
{
int arr[] = { 1,2,3 };
std::cout << len(arr) << std::endl;
}
使用 g++ 时,第一个程序按预期编译和运行。但第二个不编译。这是诊断:
b.cc: In function ‘int main()’: b.cc:13:25: error: no matching function for call to ‘len(int [3])’ std::cout << len(arr) << std::endl; ^ b.cc:7:13: note: candidate: template<class T, long unsigned int n> std::size_t len(T*) std::size_t len(T v[n]) { return n; } ^ b.cc:7:13: note: template argument deduction/substitution failed: b.cc:13:25: note: couldn't deduce template parameter ‘n’ std::cout << len(arr) << std::endl;
为什么编译器能够在第一种情况下推断出数组中的项目数,而在第二种情况下却不能?是什么使得在 C++11 或 C++17 标准中必须编写 T (&v)[n] 而不是 T v[n]?
【问题讨论】:
-
我不打算去寻找参考(因为我觉得这是一个相当众所周知的事实),但是函数参数中的
T x[N]完全,完全等同于T *x。 -
... 但
T(&x)[N]不等于T * const (&x)?!? -
不,此规则不适用于递归。它仅适用于数组。
T x[N]是一个数组,所以它适用于它,T(&x)[N]是一个引用而不是数组,所以它不适用(对数组的引用,是的,但它的引用无关紧要)。 -
我想我明白你的意思了。谢谢。
标签: c++ c++11 templates c++17 language-lawyer