以下代码无法编译:
ParseGeoPoint.getCurrentLocationInBackground(10000, new LocationCallback() {
@Override
public void done(ParseGeoPoint geoPoint, ParseException e) {
if (e!=null)
Print("location not found " + e.getLocalizedMessage());
else
{
Print("location found ");
}
}
});
如果我将template <int N>
void f(char[N]) {}
int main() {
char buf[10];
f(buf);
}
更改为char[N]
,则可行。那么它们之间有什么区别呢?
答案 0 :(得分:7)
你被C语言的向后兼容性所困扰。当你声明一个像:
这样的函数时int f(char c[10]);
声明一个参数类型为char *
的函数。编译器为您解析参数类型。问题是:
int f(char c[5]);
声明相同的函数。这就是C的工作方式,C ++保留了它的兼容性。
int f(char (&c)[10]);
声明一个函数,其参数类型为“对char的数组(长度为10)的引用”。 C没有引用,因此不需要保持向后兼容性。
int f(char (&c)[5]);
使用不同的参数类型声明不同的函数。
答案 1 :(得分:2)
显然,您知道char [N]
是一个数组,而char (&)[N]
是对char [N]
的引用。
c样式数组在按值作为参数传递时是特殊的。数组本身没有传递,但引用是。
这种“魔力”是c ++从C演变的历史副作用。
按值传递数组这些天我们使用std::array<char, N>
来封装c风格的数组。
请注意char (&)[N]
被视为文字类型,因此可以传递给constexpr上下文中的constexpr
函数。
答案 2 :(得分:2)
我认为事件的顺序是
char[10]
函数,因为该语言不支持将数组作为值传递。char[10]
的函数(并且找不到任何函数)。char
的指针,这是在称为类型调整之后的实际参数类型,并且没有找到任何最后一点很有意思,因为模板函数f
实际上确实带有一个指向char 的指针,正如其他海报所解释的那样:声明中的索引是多余的,并且在函数声明中f(char p[])
p
不是类型数组,而是类型指向char的指针。请注意,这与其他地方的声明(不作为函数参数)不同,其中p
将是一个数组,尽管不完整。
编译器无法实例化函数模板的原因并不是它的参数类型错误:它会在参数类型调整后匹配。原因很简单,它无法从参数中推断出模板参数N
。毕竟,对于每个N
,都会有不同的f
:哪一个应该编译器采取??实际论证buf
已被&#34;调整后#34;对于指向其第一个元素的指针,参数中的长度信息将丢失。 (是的,编译器是愚蠢的。)
当您将函数声明为对数组的引用时,保留了长度信息。
另一种可能性是简单地实例化模板函数:
f<10>(buf);
有效。