Question: ```
#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 ). Shouldn't F2 be called? Why is the call ambiguous?

Answer: 
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.

```
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**. If one function has the best conversion for every argument, that's the one that's called. If there's no function that's best for every argument, the call is ambiguous.

For the first argument, the type of the argument is `double`. Calling the first version of `foo` requires a conversion from `double` to `int`; calling the second version of `foo` requires no conversion; it's an exact match. So for the first argument, the second version of `foo` has the best conversion.

For the second argument, the type of the argument is `short`. Calling the first version of `foo` requires no conversion; it's an exact match. Calling the second version of `foo` requires a promotion from `short` to `int`. So for the second argument, the first version of `foo` has the best conversion.

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.
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. 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.

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. But in this case, the second argument is of type `short` while the second parameter is of type `int`. So a promotion to `int` is needed for the second argument.

---

#### Result 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`. Thus, the first overloaded candidate is not a better match than the second overloaded candidate.

---

#### Result 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.