【问题标题】:Overloading Function templates Rules重载函数模板规则
【发布时间】:2025-11-27 20:05:03
【问题描述】:

以下sn-p来自C++模板第2版一书。

template<typename T1, typename T2>
auto max (T1 a, T2 b)
{
return b < a ? a : b;
}
template<typename RT, typename T1, typename T2>
RT max (T1 a, T2 b)
{
return b < a ? a : b;
}

auto b = ::max<long double>(7.2, 4); // uses second template

我的问题是为什么 ::max(7.2, 4) 使用第二个模板?两个函数模板不应该匹配吗,因为 long double 可以是 T1 或 RT 的类型?有什么提示吗?谢谢!

【问题讨论】:

  • 7.2double,而不是 long double。所以第二个模板是更好的匹配。
  • 但是对于第二个模板,返回值也应该是long double,这也需要从doubleint隐式转换为long double,这样对于第一个或第二个,都有是隐式转换吗?
  • 是的。但是返回值/类型在模板推导中不起作用。只有参数传递给函数。在选择使用哪个重载时,甚至从不查看函数的主体。只有函数签名。

标签: c++ templates overload-resolution function-templates


【解决方案1】:

对于第一个重载,如果将T1 指定为long double,并传递7.2,即double,则需要从doublelong double 的隐式转换。对于第 2 次重载,RT 指定为 long doubleT1 将推导出为 double,因此它是完全匹配并在重载解析中获胜。

如果您将模板参数指定为double::max&lt;double&gt;(7.2, 4);,则两者都是完全匹配的,并且调用将不明确。

【讨论】:

  • 有一个后续问题。对于第二次重载,T1 将被推断为doubleT2 将被推断为int。返回值也应该是double,这也需要将double隐式转换为long double
  • @Willi 是的,返回时需要隐式转换。但是overload resolution 不考虑return 语句和返回值。 一般来说,参数与参数最接近的候选函数就是被调用的函数。
【解决方案2】:

我认为这是因为 T1T2 可以由编译器自动设置为您传递给 (7.2,4) 的参数(T1 现在将是 doubleT2 现在将是 intlong),但您还包含另一个类型名(并且您没有任何其他接受一个类型名的重载),因此编译器认为long double 是第二个重载的第一个参数,而自动其他两个。

【讨论】: