以下代码是在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
}
Run Code Online (Sandbox Code Playgroud)
它似乎归结为做出f(int *)决议f<int *>(int *)而不是预期的召唤f(const int *).我发现这令人震惊,完全不直观.
这是g ++中的一个错误,是C++的一个黑暗角落,还是由于某种原因我很遗憾?如果它不是一个错误,它背后的理论或逻辑是什么?有关此问题的安全措施吗?
对于实例化的模板,f<int *>不需要转换(int *- > const int *),因此它是一个更好的匹配 - 实际上,它是一个完全匹配,只会对非模板化的精确匹配丢失,这就是第二次调用所发生的情况.
有关"更好匹配"规则的完整说明,请参见C++标准的第13.3.3节.
那么,为什么在调用时将函数的 const 版本称为“预期”呢f(&x)?
int *正如您所知,参数类型是。因此,f(int *)函数的版本比版本更好匹配f(const int *),因为在前者中,参数类型完全匹配。f(int *)编译器看到从模板生成的机会,并抓住这个机会。这就是 C++ 中的工作原理。
如果模板版本与非模板版本一样好,那么非模板版本通常会获胜。但在这种情况下,模板版本明显更好,因此模板版本获胜。
显然您希望编译器选择该函数的非模板版本。为什么?