【问题标题】:Template overload resolution: what happens when multiple templates match?模板重载解析:多个模板匹配时会发生什么?
【发布时间】:2019-09-27 06:30:27
【问题描述】:

以下程序打印T,T

#include <iostream>

template<typename T>
void f(T x, T y) {
  std::cout << "T,T\n";
}

template<typename T1, typename T2> 
void f(T1 x, T2 y) {
  std::cout << "T1,T2\n";
}

int main() {
  f(1, 1); 
  return 0;
}

在代码中哪个模板排在第一位没有区别。

我希望重载决议在这里是模棱两可的。 TT1T2 都应该推导出为 int,这使得两个模板都与调用站点完全匹配。

我找不到任何解析规则 (https://en.cppreference.com/w/cpp/language/overload_resolution) 来解释为什么它会选择第一个模板。

我使用clang++ -std=c++17 进行了测试,以防万一。

【问题讨论】:

  • 相同的模板参数(TT)优于不同的模板参数(T1T2)作为决胜局。

标签: c++ templates overload-resolution


【解决方案1】:

overloaded function templates 进行部分排序以确定应该选择哪一个。

当同一个函数模板特化匹配多个时 重载的函数模板(这通常由模板导致 参数推导),重载函数模板的部分排序 执行以选择最佳匹配。

具体来说,部分排序发生在下面 情况:

1) 函数模板调用的重载决议 专业化

template<class X> void f(X a);
template<class X> void f(X* a);
int* p;
f(p);

2) ...

...

通俗地说,“A 比 B 更专业”的意思是“A 接受的类型比 B 少”。

选择第一个重载是因为它只接受一种相同类型的参数,而第二个重载可以接受两种独立类型的参数。

【讨论】:

  • 如果有兴趣,请参阅链接页面以了解有关正式规则的更多详细信息,这要复杂得多。
  • 该规则的最终结果也是非模板重载也是“最专业的”。
【解决方案2】:

也许答案的一部分在这里Implicit_instantiation

当代码在上下文中引用需要函数定义存在的函数,并且该特定函数尚未显式实例化时,就会发生隐式实例化。如果可以从上下文中推导出模板参数列表,则不必提供它

编译器将调用f(1, 1) 与实例化f&lt;int&gt; 连接起来。当在代码中删除第一个模板 (template&lt;typename T&gt; void f(T x, T y)) 时,编译器将调用 f(1, 1) 与实例化 f&lt;int, int&gt; 连接起来。 您可以使用明确的类型指示来调用每个实例化:

f(1, 1);
f<int>(1, 1);
f<int, int>(1, 1);

输出是:

T,T
T,T
T1,T2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多