以下程序打印T,T
.
#include <iostream>
template<typename T>
void f(T x, T y) {
std::cout << "T,Tn";
}
template<typename T1, typename T2>
void f(T1 x, T2 y) {
std::cout << "T1,T2n";
}
int main() {
f(1, 1);
return 0;
}
哪个模板在代码中排在第一位没有区别。
我希望重载解决方案在这里是模棱两可的。T
、T1
和T2
都应该推导为int
,这使得两个模板都与调用站点完全匹配。
我无法找到任何解析规则 (https://en.cppreference.com/w/cpp/language/overload_resolution( 来解释为什么它会选择第一个模板。
我用clang++ -std=c++17
进行了测试,以防万一。
对重载的函数模板执行部分排序以确定应选择哪一个。
当同一函数模板专用化匹配多个函数模板时 重载函数模板(这通常是由模板引起的 参数推导(,重载函数模板的部分排序 以选择最佳匹配项。
具体而言,部分排序发生在以下位置 情况:
1( 调用函数模板的重载解析 专业化
template<class X> void f(X a); template<class X> void f(X* a); int* p; f(p);
2( ...
。
非正式地说,"A 比 B 更专业"意味着"A 接受的类型比 B 少"。
选择第一个重载是因为它只接受具有一种相同类型的参数,而第二个重载可以接受具有两种独立类型的参数。
也许答案的一部分就在这里Implicit_instantiation
当代码引用上下文中需要函数定义的函数存在,并且此特定函数尚未显式实例化时,将发生隐式实例化。如果可以从上下文中推导出模板参数列表,则不必提供模板参数列表
编译器将调用f(1, 1)
与实例化f<int>
连接。当代码中的第一个模板(template<typename T> void f(T x, T y)
(被删除时,编译器将调用f(1, 1)
与实例化f<int, int>
连接。 您可以使用显式类型指示来调用每个实例化:
f(1, 1);
f<int>(1, 1);
f<int, int>(1, 1);
输出为:
T,T
T,T
T1,T2