C++ 使用非常量指针调用函数会在使用常量指针的函数上调用模板函数
以下代码是在g++4.1.2和g++4.4.4上编译的。两者都给出了评论中提到的结果C++ 使用非常量指针调用函数会在使用常量指针的函数上调用模板函数,c++,C++,以下代码是在g++4.1.2和g++4.4.4上编译的。两者都给出了评论中提到的结果 int f(const int * a) { return 0; } template<typename A> int f(A a) { return 1; } int main() { int x; // return f(&x); // returns 1 return f((const int *)&x); // returns 0 }
int f(const int * a)
{
return 0;
}
template<typename A>
int f(A a)
{
return 1;
}
int main()
{
int x;
// return f(&x); // returns 1
return f((const int *)&x); // returns 0
}
intf(常数int*a)
{
返回0;
}
模板
INTF(A)
{
返回1;
}
int main()
{
int x;
//返回f(&x);//返回1
返回f((常量int*)&x);//返回0
}
它似乎可以归结为调用f(int*)
解析为f(int*)
,而不是预期的f(const int*)
。我觉得这令人震惊,完全不直观
这是G++中的一个bug,C++的一个暗角,还是因为某种原因我失踪了?如果它不是一个bug,那么它背后的理论或逻辑是什么?关于这个问题有什么安全的做法吗?
那么,在调用f(&x)
的情况下,为什么要调用const版本的函数“expected”
如您所知,参数类型是int*
。因此,函数的f(int*)
版本比f(const int*)
版本更匹配,因为前者的参数类型完全匹配。编译器看到了从模板生成f(int*)
的机会,并抓住了这个机会。这就是它在C++中的工作原理。p>
如果模板版本与非模板版本一样好,则非模板版本通常获胜。但在这种情况下,如果模板版本明显更好,则模板版本将获胜
显然,您希望编译器选择函数的非模板版本。为什么?对于实例化的模板
f
不需要转换(int*
->const int*
),因此它是一个更好的匹配-实际上,它是一个精确匹配,只会输给非模板精确匹配,这是第二次调用的情况
<> P.>对“更好匹配”规则的完整解释可在C++标准的“3.3.3”中获得。> > f(int)和<代码> f(const int)<代码>是相同的原型,只要ANSI C++编译器是一致的,但是<代码> f(INT*) >与<代码> f(const int *)/f(int const)可能不一样。链接:+1提供一个最小的完整示例程序。看看为什么这是个好主意。@sehe“也许”?我认为你误读了那个环节的讨论。“foo(int*const a)”接受一个指向int的常量指针。在这里的示例中,“f(const int*a)”接受指向int的指针。由于一个简单的隐式常量转换,我希望它会赢。在我看来,const升级指针类型总是在考虑模板之前进行,这似乎是明智的。也许有一个例子说明了为什么这不是一个好主意。@Roland:No conversion>overload resolution中的琐碎转换。@Roland:假设您有两种方法来执行一个操作。(就其论点而言)它是破坏性的。因此,在
const
版本中,您需要首先执行参数的副本,这显然效率较低。示例:T&&operator+(T&&,T const&)
比T operator+(T const&,T const&)
更有效。在这种情况下,我同意,因为它们都是模板。我的意思是,在考虑任何模板之前,我希望隐式常量转换。