用const实参重载实参演绎的c++模板函数

c++ template function overlading argument deduction with const argument

本文关键字:实参 c++ 函数 演绎 const 重载      更新时间:2023-10-16

我有以下设置:

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的类型不匹配。在第二次调用中,调用非模板版本。我使用的是微软c++编译器版本10。这是标准行为吗?如果类型不完全匹配,即使只有const修饰符,也会调用模板函数。

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

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

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

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

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

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

——上下文是用户自定义转换的初始化(参见8.5、13.3.1.5和13.3.1.6)从返回类型F1到目的类型(即,类型)的标准转换序列实体被初始化)是一个比标准转换序列更好的转换序列将F2的返回类型转换为目标类型。[…]或者,如果不是,

- F1是非模板函数,F2是函数模板专门化,如果不是,则

— [...]

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

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

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

应该可以了

#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();
}