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

时间:2018-10-02 13:51:48

标签: c++ templates overload-resolution template-deduction

我声明了两个模板,第一个将参数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';
}

2 个答案:

答案 0 :(得分: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);

然后我们替换:

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

目前,尚无可推论的类型。所以我们去解决重载问题。

在一种情况下,我们可以采用int并在 calling 转换时转换为float,在另一种情况下,我们可以采用int并转换为int进行呼叫投射时。请注意,我并没有考虑演员的 body ;身体与超载解决方案无关。

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

如果您这样做:

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);

因此,这里有一个可行的重载,并且被使用了。

答案 1 :(得分:2)

实例化不是模棱两可的,因为function参数与第一个模板参数完全匹配:文字0 <= i < needle.length10,它也为第一个模板类型明确指定。

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

int