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

时间:2023-01-22 20:39:51

I declare two templates, the first converts the argument x from type T to type U and the second from type U to type T. If I call cast with 10, the compiler does not complain. I think both meet the requirements to be used and therefore there should be ambiguity, is that true? This code prints 10.

我声明了两个模板,第一个将参数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 个解决方案

#1


24  

When you use cast<int, float>, both templates are considered.

使用cast 时,会考虑两个模板。 ,float>

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

we then substitute:

然后我们替换:

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

at this point, there are no types to deduce. So we go to overload resolution.

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

In one case, we can take an int and convert to float when calling cast, and in the other we take a int and convert to int when calling cast. Note I'm not looking at all into the body of cast; the body is not relevant to overload resolution.

在一种情况下,我们可以在调用cast时获取一个int并转换为float,而在另一种情况下,我们在调用cast时获取一个int并转换为int。注意我并没有全神贯注于演员的身体;身体与超载分辨率无关。

The second non-conversion (at the point of call) is a better match, so that overload is chosen.

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

If you did this:

如果你这样做:

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

things get more interesting:

事情变得更有趣:

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

for the first one, we cannot deduce U. For the second one we can.

对于第一个,我们不能推断出U.对于第二个我们可以。

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

so here we have one viable overload, and it is used.

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

#2


2  

The instantiation is not ambiguous because the function argument exactly matches the first template parameter: the literal 10 is an int, which is also explicitly specified for the first template type.

实例化不是模糊的,因为函数参数与第一个模板参数完全匹配:文字10是一个int,也是为第一个模板类型明确指定的。

You can make the instantiation ambiguous when the argument type does not match the explicitly specified types (thus, a conversion is necessary), e.g.

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

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

#1


24  

When you use cast<int, float>, both templates are considered.

使用cast 时,会考虑两个模板。 ,float>

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

we then substitute:

然后我们替换:

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

at this point, there are no types to deduce. So we go to overload resolution.

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

In one case, we can take an int and convert to float when calling cast, and in the other we take a int and convert to int when calling cast. Note I'm not looking at all into the body of cast; the body is not relevant to overload resolution.

在一种情况下,我们可以在调用cast时获取一个int并转换为float,而在另一种情况下,我们在调用cast时获取一个int并转换为int。注意我并没有全神贯注于演员的身体;身体与超载分辨率无关。

The second non-conversion (at the point of call) is a better match, so that overload is chosen.

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

If you did this:

如果你这样做:

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

things get more interesting:

事情变得更有趣:

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

for the first one, we cannot deduce U. For the second one we can.

对于第一个,我们不能推断出U.对于第二个我们可以。

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

so here we have one viable overload, and it is used.

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

#2


2  

The instantiation is not ambiguous because the function argument exactly matches the first template parameter: the literal 10 is an int, which is also explicitly specified for the first template type.

实例化不是模糊的,因为函数参数与第一个模板参数完全匹配:文字10是一个int,也是为第一个模板类型明确指定的。

You can make the instantiation ambiguous when the argument type does not match the explicitly specified types (thus, a conversion is necessary), e.g.

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

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