c ++模板函数使用const参数重载参数推导

时间:2013-03-24 16:36:01

标签: c++ templates overloading

我正在进行以下设置:

template <typename T>
void foo(T& t);
void foo(const int& t);

void f()
{
    int i;
    foo(i); //Unresolved reference to "void foo<int>(int &)"
    foo(const_cast<const int&>(i)); //Unresolved reference to "void foo(int const &)"
}

在第一次调用foo时,编译器会尝试调用模板版本,因为非模板版本的参数与 i 的类型不匹配。在第二次调用中,调用非模板版本。我使用的是Microsoft C ++编译器版本10.这是标准行为吗?如果类型不完全匹配,即使它只有一个const修饰符,那么模板函数也会被调用?

编辑:我知道这两个函数没有定义,我只是指出链接器抱怨的内容,以便更清楚编译器想要调用的内容。

3 个答案:

答案 0 :(得分:4)

,根据C ++ 11标准,此行为是正确的。

在第一种情况下,参数是对非const整数的引用。这两个重载都可以解决此调用,但函数模板允许完美匹配,而非模板重载需要资格转换。

在第二种情况下,两者都是完美匹配,但其中一个重载是一个函数模板,因此它比函数模板更好。事实上,根据§13.3.3/ 1:

  

鉴于这些定义,一个可行的函数F1被定义为比另一个可行函数更好的函数   对于所有参数i,如果为F2,则ICSi(F1)的转换序列不比ICSi(F2)差,然后

     

- 对于某些参数j,ICSj(F1)是比ICSj(F2)更好的转换序列,或者,如果不是,

     

- 上下文是用户定义转换的初始化(见8.5,13.3.1.5和13.3.1.6)和   从返回类型F1到目标类型的标准转换序列(即,类型的   正在初始化的实体)是比标准转换序列更好的转换序列   F2的返回类型到目标类型。 [...]或者,如果不是那样,

     

- F1是非模板功能,F2是功能模板专业化,或者,如果不是,

     

- [...]

答案 1 :(得分:2)

  

这是标准行为吗?如果类型不完全匹配,即使它只有一个const修饰符,那么模板函数也会被调用?

是的,标准明确定义了这一点。

如果没有EXACT匹配,则使用模板,因为实例化的模板版本始终是更好匹配,而不是需要转换的版本(即使是int &到{{1转换)。

答案 2 :(得分:-1)

这应该有效

#include <iostream>

template <typename T>
void foo(T& t) {}
void foo(const int& t){}

void f() 
{
    int i;
    foo(i); //Unresolved reference to "void foo<int>(int &)"
    foo(const_cast<const int&>(i)); //Unresolved reference to "void foo(int const &);
}

int main()
{
    f();
}