为什么这个模板的调用不明确?

wic*_*wic 18 c++ templates overload-resolution template-argument-deduction

我声明了两个模板,第一个将参数x从type 转换T为type U,第二个从type转换U为type T.如果我cast用10 调用,编译器不会抱怨.我认为两者都符合要求使用,因此应该有歧义,这是真的吗?此代码打印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';
}
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 24

使用时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);
Run Code Online (Sandbox Code Playgroud)

然后我们替换:

template<typename T=int,typename U=float>
float cast(int x);
template<typename T=int,typename U=float>
int cast(float x);
Run Code Online (Sandbox Code Playgroud)

在这一点上,没有类型可推断.所以我们去重载决议.

在一个案例中,我们可以采取int并转换为float调用投,而在另一方面,我们采取了int和转换int调用演员.注意我并没有全神贯注于演员的身体 ; 身体与超载分辨率无关.

第二次非转换(在调用点)是更好的匹配,因此选择了重载.

如果你这样做:

std::cout << cast<int>(10) << "\n";
Run Code Online (Sandbox Code Playgroud)

事情变得更有趣:

template<typename T=int,typename U=?>
U cast(T x);
template<typename T=int,typename U=?>
T cast(U x);
Run Code Online (Sandbox Code Playgroud)

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

template<typename T=int,typename U=?>
U cast(int x);
template<typename T=int,typename U=int>
int cast(int x);
Run Code Online (Sandbox Code Playgroud)

所以这里有一个可行的重载,并且它被使用了.