c++ - 查找调用了哪个模板函数重载的规则

标签 c++ templates

//(1)
template <class T>
void f(T) {}

//(2)
template <class T>
void f(T*) {}

//(3)
template <>
void f<>(int*) {}

//(4)
void f(int*) {}

int main()
{
  int* p;
  f(p); // which function will be called?
  return 0
}

我已经知道这种行为:

  • 这取决于是否存在过载 (4)。
  • 取决于(1)、(2)、(3)的声明顺序

令我困扰的是顺序很重要(因为它在我编写代码时增加了不确定性和猜测工作),尤其是我知道如果这些是类特化,那么顺序就无关紧要,编译器会调用最专业的类。

有人可以向我解释这是如何工作的吗?编译器遵循哪些规则来找到合适的函数特化?

最佳答案

基本规则实际上相当简单:函数和函数模板参与重载决策。显式函数模板特化不要。

因此,对于调用 f(p),编译器会进行重载决策以在 (1)、(2) 和 (4) 之间进行选择。 (3) 从不考虑重载决议。

重载解析选择单个函数或函数模板。 完成后,如果它选择了一个函数模板,然后将考虑该模板的特化。

让我们分析您提供的声明的不同组合。

  • 如果 (4) 存在,它将被明确选择。当其他一切都相同时,非模板函数比函数模板更适合重载。

  • 假设我们按顺序只有 (1)、(2) 和 (3)。过载解决方案在 (1) 和 (2) 之间选择。 (2) 更好,因为它更专业。所以函数模板(2)是由重载决议选择的。

    然后,编译器会查看模板是否有任何特化。事实上,它确实如此——特化 (3),对于 T = int。所以选择了这个专业。

  • 现在,假设顺序是 (1)、(3)、(2)。同样,重载决策在 (1) 和 (2) 之间进行选择(记住特化,即 (3) 永远不会参与重载决策)。 (2) 再次选择。这一次,(3) 是 (1) 的特化,对于 T = int*。这是因为当 (3) 被声明时 (2) 还不存在,所以没有 (2) 可以专门化。但是 (1) 没有被重载决策选择,所以没有考虑。

  • (2)、(3)、(1)的顺序与(1)、(2)、(3)相同。 (2)、(1)、(3)的顺序与(1)、(3)、(2)相同。 (1) 和 (2) 的相对顺序无关紧要 - (3) 的位置决定了它将专门化哪个模板。

关于c++ - 查找调用了哪个模板函数重载的规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29432792/

相关文章:

c++ - 插入迭代器如何在 C++ 中工作

c++ - 令人费解的非尾随参数包行为

c++ - 如何专门化 std::vector<T> 的模板成员函数

c++ - [expr.ref]/1 中提到的脚注到底是什么意思?

c++ - boost::asio 使用链严格顺序调用事件处理程序

c++ - 在 boost::spirit::x3 中用作标记的奇怪结构

c++ - 具有模板构造函数特化的模板类,用于初始化模板化基类

c++ - 以亚像素精度检测激光线的中心

C++: 'set' 和 'vector'“尽管有#include 语句但未声明

Android NDK - 没有这样的文件或目录编译终止 - 头文件导出问题