为什么对模板的调用不模棱两可?

Why isn't this call to a template ambiguous?

本文关键字:模棱两可 调用 为什么      更新时间:2023-10-16

我声明了两个模板,第一个将参数x从类型T转换为类型U,第二个从类型U转换为类型T。如果我用 10 调用cast,编译器不会抱怨。我认为两者都符合使用要求,因此应该有歧义,这是真的吗?此代码打印 10。

#include <iostream>
template<typename T, typename U>
U cast(T x) {
return static_cast<U>(x);
}
template<typename T, typename U>
T cast(U x) {
return static_cast<T>(x);
}
int main() {
std::cout << cast<int,float>(10) << 'n';
}

当您使用cast<int, float>时,会考虑这两个模板。

template<typename T=int,typename U=float>
U cast(T x);
template<typename T=int,typename U=float>
T cast(U x);

然后我们替换:

template<typename T=int,typename U=float>
float cast(int x);
template<typename T=int,typename U=float>
int cast(float x);

此时,没有要推断的类型。 所以我们去重载解决。

在一种情况下,我们可以在调用cast 时采用int并转换为float,而在另一种情况下,我们可以采用int并在调用cast 时转换为int。 注意,我根本不在看演员的身体;主体与过载分辨率无关。

第二个非转换(在调用点(是更好的匹配,因此选择重载。

如果您这样做:

std::cout << cast<int>(10) << "n";

事情变得更加有趣:

template<typename T=int,typename U=?>
U cast(T x);
template<typename T=int,typename U=?>
T cast(U x);

对于第一个,我们无法推断U. 对于第二个我们可以。

template<typename T=int,typename U=?>
U cast(int x);
template<typename T=int,typename U=int>
int cast(int x);

所以这里我们有一个可行的重载,它被使用。

实例化不是模棱两可的,因为函数参数与第一个模板参数完全匹配:文字10是一个int,它也为第一个模板类型显式指定。

当参数类型与显式指定的类型不匹配时,可以使实例化变得不明确(因此,需要进行转换(,例如

// error: call of overloaded 'cast<int, float>(unsigned int)' is ambiguous
std::cout << cast<int,float>(10u) << "n";