我有这些C ++代码:
在" header1.h"
template <typename T>
int f1(const T& t1) {
return 0;
}
extern const int p[];
在cpptests.cpp
中#include "header1.h"
int _tmain(int argc, _TCHAR* argv[]) {
f1(p);
return 0;
}
在VC ++ 2010中,我遇到了这个编译错误:
c:\work\cpptests\cpptests\cpptests.cpp(10): error C2664: 'f1' : cannot convert parameter 1 from 'const int []' to 'const int (&)[1]'
Reason: cannot convert from 'const int []' to 'const int [1]'
There is no context in which this conversion is possible
Generating Code...
Wny模板函数调用将p转换为const int (&)[1]
?
答案 0 :(得分:3)
变量p
的类型是“const int
未知范围的数组”。通过C ++ 11 8.3.5,“函数”,
如果参数的类型包含[...]“对
T
未知界限数组的引用”的类型,则该程序格式不正确。
请允许我进行一些精神上的游览,了解为什么这有意义:
您可能知道即使类型T
不完整,类型T *
和T &
也是完整类型。 C ++包含一种奇怪的机制,通过该机制,变量的类型可以通过 completed 来改变。也就是说,您可以声明一个变量T x;
,它具有不完整的类型,但稍后完成变量定义中的类型。例如,取T = int[]
:
extern int a[]; // `a` has incomplete type "array of unknown bound of int"
int a[10]; // now `a` has complete type "array of 10 int"
然而(参见3.9 / 6),假设我们现在有另一个指针类型T *
的变量:
int (*p)[] = &a; // `p` is a pointer to an array of unknown bound
此变量的类型已经完成,但它的“数组”部分永远无法完成。因此,即使a
最终可能具有完整类型,类型p
也永远不会改变。它的类型永远不会变成int (*)[10]
。两种类型都已完成,后者不完成前者。
这意味着您永远不能使用 p
来访问整个数组对象。你仍然可以通过将p
衰减到指向数组第一个元素的指针来使用*p
(注意*p
是一个非常精细的左值; glvalues不需要有完整的类型),但是你永远无法通过p
看到整个数组。 (同样的推理适用于T &
。)
由于对未知边界数组的指针和引用具有如此有限的实用性,因此不允许它们作为函数参数类型。在您的情况下,推导出的类型恰好是“未知界限数组”类型,因此生成的程序格式不正确。