我正在进行以下设置:
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修饰符,那么模板函数也会被调用?
编辑:我知道这两个函数没有定义,我只是指出链接器抱怨的内容,以便更清楚编译器想要调用的内容。答案 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();
}