以下代码是在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
}
似乎可以归结为f(int *)
调用f<int *>(int *)
而不是预期的f(const int *)
。我发现这令人震惊,完全不直观。
这是g ++中的一个错误,是C ++的一个黑暗角落,还是由于某些原因而显而易见的我错过了?如果它不是一个错误,它背后的理论或逻辑是什么?关于这个问题,有没有安全的做法?
答案 0 :(得分:8)
对于实例化的模板f<int *>
,不需要转换(int *
- &gt; const int *
),因此这是一个更好的匹配 - 实际上,它是完全匹配,只会丢失非模板化的完全匹配,这是第二次调用所发生的。
“更好匹配”规则的完整说明可在C ++标准的第13.3.3节中找到。
答案 1 :(得分:4)
那么,为什么在f(&x)
调用的情况下调用函数的const版本是“期望的”?
正如您所知,参数类型为int *
。因此,f(int *)
版本的函数比f(const int *)
版本更好,因为在前者中,参数类型与完全匹配。编译器看到了从模板生成f(int *)
的机会,并抓住了这个机会。这就是它在C ++中的工作原理。
如果模板版本与非模板版本一样好,则非模板版本通常会获胜。但在这种情况下,模板版本显然更好,模板版本获胜。
显然,您希望编译器选择该函数的非模板版本。为什么呢?