简体   繁体   English

Function重载规则含糊不清? (精确 > 提升 > 转换)

[英]Ambiguity in Function Overloading Rules? (Exact > Promote > Convert)

#include <string>
void foo(int x, short y, int z) { std::cout << "normal int" << std::endl; } //F1
void foo(double x, int y, double z) { std::cout << "normal double" << std::endl; } //F2

int main()
{
    short x = 2;
    foo(5.0, x, 8.0);
}

Based on function overloading rules, F1( Exact = 1, Promote = 0, Convert = 2 ) and F2( Exact = 2, Promote = 1, Convert = 0 ).基于 function 重载规则,F1( Exact = 1, Promote = 0, Convert = 2 ) 和 F2( Exact = 2, Promote = 1, Convert = 0 )。 Shouldn't F2 be called?不应该调用 F2 吗? Why is the call ambiguous?为什么调用不明确?

Overload resolution can get complicated.过载解决方案可能会变得复杂。 But here it's fairly straightforward.但在这里它相当简单。 I'll rewrite the function prototypes to remove the third argument, since it doesn't affect the analysis.我将重写 function 原型以删除第三个参数,因为它不会影响分析。

void foo(int, short);
void foo(double, int);

double d = 1.0;
short s = 2;

f(d, s); // ambiguous

The rule is that you look at each argument, one at a time, and determine which function has the "best" conversion for that argument .规则是您查看每个参数,一次一个,并确定哪个 function对该参数具有“最佳”转换。 If one function has the best conversion for every argument, that's the one that's called.如果一个 function 对每个参数都有最好的转换,那就是那个被调用的。 If there's no function that's best for every argument, the call is ambiguous.如果没有最适合每个参数的 function,则调用是不明确的。

For the first argument, the type of the argument is double .对于第一个参数,参数的类型是double Calling the first version of foo requires a conversion from double to int ;调用第一个版本的foo需要从doubleint的转换; calling the second version of foo requires no conversion;调用第二个版本的foo不需要转换; it's an exact match.这是一个完全匹配。 So for the first argument, the second version of foo has the best conversion.因此对于第一个参数, foo的第二个版本具有最佳转换。

For the second argument, the type of the argument is short .对于第二个参数,参数的类型是short Calling the first version of foo requires no conversion;调用foo的第一个版本不需要转换; it's an exact match.这是一个完全匹配。 Calling the second version of foo requires a promotion from short to int .调用foo的第二个版本需要从short升级到int So for the second argument, the first version of foo has the best conversion.所以对于第二个参数,第一个版本的foo有最好的转换。

Since the first version of foo has the best match for the second argument and the second version of foo has the best match for the first argument, there is no function with the best match on all arguments, and the call is ambiguous.由于foo的第一个版本与第二个参数具有最佳匹配,而foo的第二个版本与第一个参数具有最佳匹配,因此不存在 function 与所有 arguments 的最佳匹配,调用是不明确的。

Overload resolution ranks the viable candidate functions by comparing how each argument of the call matches the corresponding parameter of the candidates.重载解析通过比较调用的每个参数与候选函数的相应参数的匹配程度来对可行的候选函数进行排序。 Moreover, for one candidate to be considered better than another, the better candidate cannot have any of its parameters be a worse match than the corresponding parameter in the other candidate .此外,对于一个被认为比另一个更好的候选者,更好的候选者不能使其任何参数比另一个候选者中的相应参数更差匹配

Now, let's apply this to your given example snippet.现在,让我们将其应用于您给定的示例代码段。

void foo(int x, short y, int z);
void foo(double x, int y, double z) ;
int main()
{
    short x = 2;
    foo(5.0, x, 8.0);
}

In the above snippet, For the case of first overloaded foo , the second argument matches exactly with the type of the second parameter.在上面的代码片段中,对于第一次重载foo的情况,第二个参数与第二个参数的类型完全匹配。 But the first and third argument have type double while the corresponding parameters have type int and so the first and the third argument requires a conversion to int in this case.但是第一个和第三个参数的类型为double ,而相应的参数的类型为int ,因此在这种情况下,第一个和第三个参数需要转换为int

On the other hand, for the case of second overloaded foo , the first and third argument matches exactly with the first and third parameter respectively.另一方面,对于第二个重载foo的情况,第一个和第三个参数分别与第一个和第三个参数完全匹配。 But in this case, the second argument is of type short while the second parameter is of type int .但在这种情况下,第二个参数是short类型,而第二个参数是int类型。 So a promotion to int is needed for the second argument.因此,第二个参数需要升级为int


Result 1结果 1

Now, according to the highlighted part at the beginning of my answer, for the first candidate to be considered a better match than the second candidate, none of the first candidate's parameter can be a worse match than the corresponding parameter in the second candidate.现在,根据我回答开头突出显示的部分,对于被认为比第二个候选者更好匹配的第一个候选者,第一个候选者的参数中没有一个比第二个候选者中的相应参数匹配更差。 But we already discussed that the first and third parameter of first overloaded candidate are worse match than the corresponding parameters in the second overloaded candidate since they require conversion to int .但是我们已经讨论过,第一个重载候选者的第一个和第三个参数比第二个重载候选者中的相应参数更差匹配,因为它们需要转换为int Thus, the first overloaded candidate is not a better match than the second overloaded candidate.因此,第一个超载候选并不比第二个超载候选匹配得更好。


Result 2结果 2

Similarly, for the second candidate to be considered a better match than the first candidate, none of the second candidate's parameter can be a worse match than the corresponding parameter in the first candidate.类似地,对于被认为比第一个候选者更好匹配的第二个候选者,第二个候选者的参数中没有一个比第一个候选者中的相应参数匹配更差。 But here also we already discussed that the second parameter in the second candidate is worse match than the corresponding parameter in the first candidate since it requires a promotion.但是这里我们也已经讨论过,第二个候选中的第二个参数比第一个候选中的相应参数匹配更差,因为它需要提升。 Thus, the second candidate is not a better match than the first candidate.因此,第二个候选者并不比第一个候选者更匹配。


Conclusion结论

Combining both of the results above, we get to the conclusion that none of the candidates is better than the other.结合以上两个结果,我们得出的结论是,没有一个候选人比另一个更好。 Hence the call is ambiguous.因此调用是不明确的。

The ranking of conversion sequences matters only when comparing ranking of the conversion sequences applied to the same argument.只有在比较应用于相同参数的转换序列的排名时,转换序列的排名才重要。

If one argument's conversion rank is better in the first overload than in the second one and the other way around for another argument's conversion rank, then neither overload is considered better than the other and the overload resolution is ambiguous.如果一个参数的转换等级在第一个重载中比在第二个重载中更好,而另一个参数的转换等级则相反,那么这两个重载都不会被认为比另一个更好,并且重载决议是不明确的。

This applies here.这适用于此。 The first and third argument have a better conversion rank (exact rather than conversion) in the second overload, while the second argument has a better conversion rank in the first overload (exact rather than promotion).第一个和第三个参数在第二个重载中具有更好的转换等级(精确而不是转换),而第二个参数在第一个重载中具有更好的转换等级(精确而不是提升)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM