I'm trying to understand the overloading resolution method.
Why is this ambiguous:
void func(double, int, int, double) {}
void func(int, double, double, double) {}
void main()
{
func(1, 2, 3, 4);
}
but this isn't?
void func(int, int, int, double) {}
void func(int, double, double, double) {}
void main()
{
func(1, 2, 3, 4);
}
In the first case there are 2 exact parameters matches and 2 conversions against 1 exact match and 3 conversions, and in the second case there are 3 exact matches and 1 conversion against 1 exact matches and 3 conversions.
So why is one ambiguous and one is not? What is the logic here?
The overload resolution rules only define a partial order on the set of all matches - if an overload
F1
is not a better match thanF2
, it does not imply thatF2
is a better match thanF1
. The exact partial order can be thought of as comparing two points ink
dimensions, where the number of arguments isk
. Lets define this partial order on points ink
-dim space -(x_1, x_2,..., x_k) < (y_1, y_2,..., y_k) if x_i <= y_i for all i and x_j < y_j for at least one j
. This is exactly the partial order on candidate non-template functions defined by the standard.Lets look at your examples :
So neither overload is strictly better than the other.
In your second example:
Now, the first overload is better than the second in all but one argument AND is never worse than the second. Thus, there is no ambiguity - the partial order does indeed declare the first one better.
(The above description does not consider function templates. You can find more details at cppreference.)
The wording from the standard (§[over.match.best]/1) is:
In your first case, the two functions fail the first test. For the first argument, the first function (taking
double
) has a worse conversion sequence than the second. For the second argument, the second function has a worse conversion sequence than the first (again, theint
has to be promoted todouble
in one case, but not the other).Therefore, neither function passes the first rule, and the call is ambiguous.
Between the second pair of functions, every argument to the the first function has at least as good of a conversion as the matching argument to the second function. We then go on to the second rule, and find that there is at least one argument (two, as a matter of fact) for which the first function has a better conversion (identity instead of promotion) than the second.
Therefore, the first function is a better match, and will be selected.
Ambiguity is determined by the ranking:
Exact match wins vs Promotion which wins vs Conversion.
In the example:
Argument 1(
1
) is an exact match on bothArgument 2(
1
) is an exact match on bothArgument 3(
3.4
) can be converted into float and int - Ambiguity Neither is better.Argument 4(
4
) is an exact match on bothBut if we did this:
func(1,1,3.4f,4);
(
3.4f
) is now an exact match!void func(int, bool, float, int)
then wins the battle.