具有多种可行类型的模板重载解析

pat*_*fox 6 c++ templates

这是用于计算最大值的 2 个模板函数

template<typename T>
auto max(T a, T b) {
  cout <<  "Calling 1\n";
  return b < a ? a : b;
}

template<typename T1, typename T2>
auto max (T1 a, T2 b) {
  cout <<  "Calling 2\n";
  return b < a ? a : b;
}
Run Code Online (Sandbox Code Playgroud)

如果我调用 max 函数如下

max(1, 2);
Run Code Online (Sandbox Code Playgroud)

选择了第一个功能(调用 1)。为什么会这样?在这种情况下,1 和 2 都可以很好地匹配。

And*_*dyG 8

这是因为,第一max更专业作为第二max

在模板重载解析期间发生的事情是编译器实例化两个模板,然后询问“哪个更专业?”

简而言之,它问,给定重载 A 和重载 B,“我可以使用从 A 推导出的类型实例化 B,反之亦然吗?” 如果是这样,那么 A 比 B 更专业(我们可以从 A 到 B,但不能返回)。它以另一种方式做同样的事情。如果两者都可以相互实例化,则是模棱两可的,并且是编译器错误。

实际上,我们不使用(在这种情况下)的实际类型,而是使用一些组合类型 ( "synthesized type" )。Tint

在您的情况下,第一个模板要求两种类型相同:

template<typename T>
auto max(T a, T b)
Run Code Online (Sandbox Code Playgroud)

所以我们有max<int>(或max<synthesized1>

我们可以实例给出的第二个synthesized1T?当然,T1 = synthesized1而且T2 = synthesized1

我们可以走另一条路吗?

第二个模板有两个参数,所以它允许a并且b是不同的类型,所以它更通用。它使用两种合成类型进行实例化:

template<typename T1, typename T2>
auto max (T1 a, T2 b)
Run Code Online (Sandbox Code Playgroud)

所以,max<synthesized2, synthesized3>

我们可以max<T>用类型synthesized2和实例化第一个synthesized3吗?不,它需要a并且b具有相同的类型。因此第一个模板更专业,编译器选择它。

参考[temp.deduct.partial]了解标准语