Pikachu
Pikachu

Reputation: 314

Ambiguous function call in C++

The following code gives the compilation error of main.cpp: In function ‘int main()’: main.cpp:18:19: error: call of overloaded ‘print(int, int)’ is ambiguous print(0, 0);

#include <iostream>

using namespace std;

void print(int, double);
void print(double, int);

int main()
{
    print(0, 0);
    return 0;
}

While the following code does not give the compilation error of function call ambiguity, why so?

#include <iostream>

using namespace std;

void print(double){}
void print(int){}

int main()
{
    print(0);
    return 0;
}

Upvotes: 1

Views: 2180

Answers (3)

Jerry Coffin
Jerry Coffin

Reputation: 490108

There are really two parts to the rules for overload resolution. Most people just talk about a "better match" or the "best match", or something similar, but (at least in my opinion) this isn't very helpful (by itself).

The rule to find that "best match" really comes in two parts. For one overload to qualify as a better match than the other, it must:

  1. have a "better" conversion sequence for at least one parameter, and
  2. have at least as "good" of a conversion sequence for every parameter.

I won't try to get into all the details about what constitutes a "better" conversion sequence, but in this case it suffices to say that the "best" conversion is no conversion at all, so leaving an int as an int is better than converting an int to a double.

In your first case, you're supplying two int arguments. Each of the available overloads has one parameter that would require a conversion from int to double, and another that would leave the int as an int.

As such, each available overload has a worse sequence than the other for at least one parameter, so neither one can be a better match than the other.

In your second case, the situation's much simpler: the overloaded functions have one one parameter apiece, and a conversion would be required for one, but no conversion would be required for the other, so the one that requires no conversion is clearly better.

The difference between the actual rules and what people tend to think based only on only hearing about a "better match" becomes especially apparent if we have (for one example) an odd number of parameters. For example, consider a situation like this:

void f(int, double, double);
void f(double, int, int);

// ...
f(1, 2, 3);

In this case, if you think solely in terms of a "better match" the second overload might seem like an obvious choice--the first requires conversions on two arguments, and the second requires a conversion on only one argument, so that seems better.

But once we understand the real rules, we recognize that this is still ambiguous. Each of the available overloads is worse for at least one argument, therefore neither qualifies as a better match.

Upvotes: 1

Shubham Jain
Shubham Jain

Reputation: 31

In the first example, when you are calling print(0,0), you are passing both integer arguments. So the compiler could try to convert either the first argument to double and call print(double, int) or it could convert second argument to double type and call the function print(int, double). In doing so, it could get confused as both of them could be a possibility for called function. Hence, it reports ambiguity.

However, in the second example, it finds clarity about the called function, i.e., print(int). Here, no type conversion is required for identifying the called function.

Upvotes: 2

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122228

Sloppy speaking, overload resolution picks the overload that is a better match considering the types of the parameters.

print(0) calls void print(int){} because 0 is an integer literal of type int.

When you call print(0, 0) then either the first 0 could be converted to double to call void print(double, int) or the second one to call void print(int, double). Neither of them is a better match, hence the compiler reports this ambiguity.

For more details i refer you to https://en.cppreference.com/w/cpp/language/overload_resolution.


Note that this is a matter of choice. The universe would not stop expanding when your example would choose to call void print(double, int) because some rules would say that thats a better match than void print(int,double), thats just not what the rules say.

Upvotes: 5

Related Questions