c++ - 使用 const 引用的函数模板重载决议

标签 c++ templates overload-resolution

我试图理解以下情况下的重载决议规则:

template<typename T>
void f(const T& x) { 
    std::cout << __PRETTY_FUNCTION__ << std::endl; //-
}

template<typename T>
void f(T& x) { // <> Überladung Variante 2
    std::cout << __PRETTY_FUNCTION__ << std::endl; //-
}

int main()
{
    int e1 = 0;
    f(e1);

    const int e2 = 0;
    f(e2); 
}

输出是:

void f(T &) [T = int]
void f(const T &) [T = int]

据我所知,第一次调用 f(e1) 会导致可行的功能

void f(const int&)
void f(int&)

从中选择第一个,因为没有删除 const 限定。

第二次调用 f(e2) 导致类型推导/可行函数

void f(const int&); // T -> int from first template overload 
void f(const int&); // T -> const int from second overload

并且输出显示选择了第一个重载。

但为什么呢?

最佳答案

当使用引用执行类型推导时,const-ness(更具体地说是 CV-ness)不会被移除。因此,在您的情况下,编译器有 2 个重载可供选择:

void f(const T &)
void f(T &)

然后,编译器在为您的 const int e2 = 0; 参数选择重载时执行“模式匹配”。第一个 const 重载是更好的匹配(更专业),因为第二个需要将 T 推导为 const int,这增加了一些东西(即 const-ness)。

模板类型推导的规则并不是非常简单,所以如果你想了解有关模板的所有细节,我强烈推荐这本书

C++ Templates: The Complete Guide作者:David Vandevoorde 和 Nicolai M. Josuttis。

它是 C++11 之前的版本,但它告诉您一切您能想到的。

PS:你必须区分实例化模板类型推导。类型推导首先发生,然后是实例化。所以在你的情况下,你没有像你最初想象的那样有 2 个模棱两可的实例化。

关于c++ - 使用 const 引用的函数模板重载决议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39269754/

相关文章:

c++ - 什么情况下new会两次返回同一个地址?

c++ - 调用空类的构造函数真的会占用内存吗?

c++ - 使用空大括号初始化程序 : pointer or reference? 的重载分辨率

c++ - 使用用户定义的函数进行字符串反转

c++ - 使用 Winsock 7 C++ 从服务器向客户端发送函数调用的最有效方法

c++ - 使用本地数组作为存储时,带有 std 字符串参数的模板类会出现段错误

c++ - 为什么这些重载不是模棱两可的?

c++ - 获取卷列表总是说 C :\

c++ - 是否可以强制 STL 集重新评估谓词?

c++ - C++ 中的重载 lambda 以及 clang 和 gcc 之间的区别