1

我有以下设置:

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 修饰符,那么调用模板函数?

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

4

3 回答 3

4

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

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

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

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

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

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

F1 是非模板函数,F2 是函数模板特化,或者,如果不是,

— [...]

于 2013-03-24T16:46:09.500 回答
2

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

是的,这是由标准明确定义的。

如果没有完全匹配,则使用模板,因为实例化的模板版本总是比需要转换的版本更好的匹配(即使是int &转换int const&)。

于 2013-03-24T16:44:11.807 回答
-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();
}
于 2013-03-24T16:43:41.643 回答