使用非const指针调用函数可以通过指向const的指针函数解析为模板函数

时间:2011-06-23 23:35:03

标签: 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
}

似乎可以归结为f(int *)调用f<int *>(int *)而不是预期的f(const int *)。我发现这令人震惊,完全不直观。

这是g ++中的一个错误,是C ++的一个黑暗角落,还是由于某些原因而显而易见的我错过了?如果它不是一个错误,它背后的理论或逻辑是什么?关于这个问题,有没有安全的做法?

2 个答案:

答案 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 ++中的工作原理。

如果模板版本与非模板版本一样好,则非模板版本通常会获胜。但在这种情况下,模板版本显然更好,模板版本获胜。

显然,您希望编译器选择该函数的非模板版本。为什么呢?