How is ambiguity determined in the overload resolution algorithm? - c++

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 than F2, it does not imply that F2 is a better match than F1. The exact partial order can be thought of as comparing two points in k dimensions, where the number of arguments is k. Lets define this partial order on points in k-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 :
void func(double, int, int, double) {}
vvv vvv vvv
better better equal
void func(int, double, double, double) {}
vvv vvv
better equal
So neither overload is strictly better than the other.
In your second example:
void func(int, int, int, double) {}
vvv vvv vvv vvv
equal better better equal
void func(int, double, double, double) {}
vvv
equal
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:
[...] let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of viable function F.
[...] a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2)
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, the int has to be promoted to double 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: no conversion required, lvalue-to-rvalue conversion, qualification conversion, user-defined conversion of class type to the same class
Promotion: integral promotion, floating-point promotion
Conversion: integral conversion, floating-point conversion, floating-integral conversion, pointer conversion, pointer-to-member conversion, boolean conversion, user-defined conversion of a derived class to its base
Exact match wins vs Promotion which wins vs Conversion.
In the example:
void func(int, bool, float, int){cout << "int,bool,float,int" << endl;}
void func(int, bool, int, int){cout << "int,int,int,int" << endl;}
int main()
{
func(1,1,3.4,4);
}
Argument 1(1) is an exact match on both
Argument 2(1) is an exact match on both
Argument 3(3.4) can be converted into float and int - Ambiguity Neither is better.
Argument 4(4) is an exact match on both
But 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.

Related

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 ). Shouldn't F2 be called? 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.
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.
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).

call to function is ambiguous, but why?

#include <iostream>
using namespace std;
void x(int a,int b){
cout<<"int int"<<endl;
}
void x(char a,char b){
cout<<"char char"<<endl;
}
int main() {
int a =2;char c ='a';
x(a,c);
return 0;
}
call to 'x' is ambiguous in apple clang compiler, why?
for x(int,int), first argument is a direct match and second is a promotion
for x(char, char) first argument is a standard conversion as I know and also according to this answer-> https://stackoverflow.com/a/28184631/13023201
And promotion should be preferred over std conversion, then x(int,int) should be called. Then why is this ambiguous??
Looking at how cppreference describes the overload resolution process:
Best viable function
For each pair of viable function F1 and F2, the implicit conversion sequences from the i-th argument to i-th parameter are ranked to determine which one is better (except the first argument, the implicit object argument for static member functions has no effect on the ranking)
F1 is determined to be a better function than F2 if implicit conversions for all arguments of F1 are not worse than the implicit conversions for all arguments of F2, and
...
x(int, int) is a better match than x(char, char) for the first argument, since int to int is an exact match and int to char is a conversion. But x(int, int) is a worse match for the second argument, because it's a promotion instead of an exact match. So neither function is a better match than the other and the overload cannot be resolved.

How come an user defined conversion is a better match than a standard integer conversion?

You can find the text below in Appendix B of the book "C++ Templates The Complete Guide" by David Vandevoorde and Nicolai Josuttis.
B.2 Simplified Overload Resolution
Given this first principle, we are left with specifying how well a
given argument matches the corresponding parameter of a viable
candidate. As a first approximation we can rank the possible matches
as follows (from best to worst):
Perfect match. The parameter has the type of the expression, or it has a type that is a reference to the type of the expression (possibly
with added const and/or volatile qualifiers).
Match with minor adjustments. This includes, for example, the decay of an array variable to a pointer to its first element, or the
addition of const to match an argument of type int** to a parameter of
type int const* const*.
Match with promotion. Promotion is a kind of implicit conversion that includes the conversion of small integral types (such as bool,
char, short, and sometimes enumerations) to int, unsigned int, long or
unsigned long, and the conversion of float to double.
Match with standard conversions only. This includes any sort of standard conversion (such as int to float) but excludes the implicit
call to a conversion operator or a converting constructor.
Match with user-defined conversions. This allows any kind of implicit conversion.
Match with ellipsis. An ellipsis parameter can match almost any type (but non-POD class types result in undefined behavior).
A few pages later the book shows the following example and text (emphasis mine):
class BadString {
public:
BadString(char const*);
...
// character access through subscripting:
char& operator[] (size_t); // (1)
char const& operator[] (size_t) const;
// implicit conversion to null-terminated byte string:
operator char* (); // (2)
operator char const* ();
...
};
int main()
{
BadString str("correkt");
str[5] = 'c'; // possibly an overload resolution ambiguity!
}
At first, nothing seems ambiguous about the expression str[5]. The
subscript operator at (1) seems like a perfect match. However, it is
not quite perfect because the argument 5 has type int, and the
operator expects an unsigned integer type (size_t and std::size_t
usually have type unsigned int or unsigned long, but never type int).
Still, a simple standard integer conversion makes (1) easily viable.
However, there is another viable candidate: the built-in subscript
operator. Indeed, if we apply the implicit conversion operator to str
(which is the implicit member function argument), we obtain a pointer
type, and now the built-in subscript operator applies. This built-in
operator takes an argument of type ptrdiff_t, which on many platforms
is equivalent to int and therefore is a perfect match for the argument
5. So even though the built-in subscript operator is a poor match (by user-defined conversion) for the implied argument, it is a better
match than the operator defined at (1) for the actual subscript! Hence
the potential ambiguity.
Note that the first list is Simplified Overload Resolution.
To remove the "possibly" and "potential" about whether or not int is the same as ptrdiff_t, let's change one line:
str[(ptrdiff_t)5] = 'c'; // definitely an overload resolution ambiguity!
Now the message I get from g++ is:
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
and --pedantic-errors promotes that warning to an error.
So without diving into the standard, this tells you that the simplified list is only part of the story. That list tells you which of several possible routes to prefer when going from A to B, but it does not tell you whether to prefer a trip from A to B over a trip from C to D.
You can see the same phenomenon (and the same g++ message) more obviously here:
struct S {
explicit S(int) {}
operator int() { return 0; }
};
void foo(const S&, long) { }
void foo(int, int) { }
int main() {
S s(0);
foo(s, 1);
}
Again the call to foo is ambiguous, because when we have a choice of which argument to implicitly convert in order to choose an overload, the rules don't say, "pick the more lightweight conversion of the two and convert the argument requiring that conversion".
Now you're going to ask me for the standard citation, but I shall use the fact I need to hit the hay as an excuse for not looking it up ;-)
In summary it is not true here that "a user defined conversion is a better match than a standard integer conversion". However in this case the two possible overloads are defined by the standard to be equally good and hence the call is ambiguous.
str.operator[](size_t(5));
Write code in definite way and you'll not need to bother about all this stuff :)
There is much more to thing about.

VS 2010 : 2 overloads have similar conversions

I don't understand what happens here
class A{};
class B : A {};
void func(A&, bool){}
void func(B&, double){}
int main(void)
{
B b;
A a;
bool bo;
double d;
func(b, bo);
}
When compiling, Visual 2010 gives me this error on line func(b, bo);
2 overloads have similar conversions
could be 'void func(B &,double)'
or 'void func(A &,bool)'
while trying to match the argument list '(B, bool)'
I don't understand why the bool parameter isn't enough to resolve the overload.
I've seen this question, and as pointed in the accepted answer, bool should prefer the bool overload. In my case, I see that first parameter isn't enough to choose the good function, but why the second parameter doesn't solve the ambiguity?
The overloading rules are a bit more complicated than you might guess. You look at each argument separately and pick the best match for that argument. Then if there is exactly one overload that provides the best match for every argument, that's the one that's called. In the example, the best match for the first argument is the second version of func, because it requires only a conversion of B to B&; the other version of func requires converting B to B& and then B& to A&. For the second argument, the first version of func is the best match, because it requires no conversions. The first version has the best match for the second argument, but it does not have the best match for the first argument, so it is not considered. Similarly, the second version has the best match for the first argument, but it does not have the best match for the second argument, so it is not considered. Now there are no versions of func left, and the call fails.
Overload resolution rules are even more complicated than Pete Becker wrote.
For each overload of f, the compiler counts not only the number of parameters for which conversion is required, but the rank of conversion.
Rank 1
No conversions required
Lvalue-to-rvalue conversion
Array-to-pointer conversion
Function-to-pointer conversion
Qualification conversion
Rank 2
Integral promotions
Floating point promotions
Rank 3
Integral conversions
Floating point conversions
Floating-integral conversions
Pointer conversions
Pointer to member conversions
Boolean conversions
Assuming that all candidates are non-template functions, a function wins if and only if it has a parameter which rank is better than the rank of the same parameter in other candidates and the ranks for the other parameters are not worse.
Now let's have a look at the OP case.
func(A&, bool): conversion B&->A& (rank 3) for the 1st parameter,
exact match (rank 1) for the 2nd parameter.
func(B&, double): exact match (rank 1) for the 1st parameter, conversion bool->double (rank 3) for the 2nd parameter.
Conclusion: noone wins.

What are the rules for choosing from overloaded template functions?

Given the code below, why is the foo(T*) function selected ?
If I remove it (the foo(T*)) the code still compiles and works correctly, but G++ v4.4.0 (and probably other compilers as well) will generate two foo() functions: one for char[4] and one for char[7].
#include <iostream>
using namespace std;
template< typename T >
void foo( const T& )
{
cout << "foo(const T&)" << endl;
}
template< typename T >
void foo( T* )
{
cout << "foo(T*)" << endl;
}
int main()
{
foo( "bar" );
foo( "foobar" );
return 0;
}
Formally, when comparing conversion sequences, lvalue transformations are ignored. Conversions are grouped into several categories, like qualification adjustment (T* -> T const*), lvalue transformation (int[N] -> int*, void() -> void(*)()), and others.
The only difference between your two candidates is an lvalue transformation. String literals are arrays that convert to pointers. The first candidate accepts the array by reference, and thus won't need an lvalue transformation. The second candidate requires an lvalue transformation.
So, if there are two candidates that both function template specializations are equally viable by looking only at the conversions, then the rule is that the more specialized one is chosen by doing partial ordering of the two.
Let's compare the two by looking at their signature of their function parameter list
void(T const&);
void(T*);
If we choose some unique type Q for the first parameter list and try to match against the second parameter list, we are matching Q against T*. This will fail, since Q is not a pointer. Thus, the second is at least as specialized as the first.
If we do the other way around, we match Q* against T const&. The reference is dropped and toplevel qualifiers are ignored, and the remaining T becomes Q*. This is an exact match for the purpose of partial ordering, and thus deduction of the transformed parameter list of the second against the first candidate succeeds. Since the other direction (against the second) didn't succeed, the second candidate is more specialized than the first - and in consequence, overload resolution will prefer the second, if there would otherwise be an ambiguity.
At 13.3.3.2/3:
Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if [...]
S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form
defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) or, if not that [...]
Then 13.3.3/1
let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and 13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.
Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then [...]
F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.5.2, or, if not that, [...]
Finally, here is the table of implicit conversions that may participate in an standard conversion sequence at 13.3.3.1.1/3.
Conversion sequences http://img259.imageshack.us/img259/851/convs.png
The full answer is quite technical.
First, string literals have char const[N] type.
Then there is an implicit conversion from char const[N] to char const*.
So both your template function match, one using reference binding, one using the implicit conversion. When they are alone, both your template functions are able to handle the calls, but when they are both present, we have to explain why the second foo (instantiated with T=char const[N]) is a better match than the first (instantiated with T=char). If you look at the overloading rules (as given by litb), the choice between
void foo(char const (&x)[4));
and
void foo(char const* x);
is ambigous (the rules are quite complicated but you can check by writing non template functions with such signatures and see that the compiler complains). In that case, the choice is made to the second one because that one is more specialized (again the rules for this partial ordering are complicated, but in this case it is because you can pass a char const[N] to a char const* but not a char const* to a char const[N] in the same way as void bar(char const*) is more specialized than void bar(char*) because you can pass a char* to a char const* but not vise-versa).
Based on overload resolution rules (Appendix B of C++ Templates: The Complete Guide has a good overview), string literals (const char []) are closer to T* than T&, because the compiler makes no distinction between char[] and char*, so T* is the closest match (const T* would be an exact match).
In fact, if you could add:
template<typename T>
void foo(const T[] a)
(which you can't), your compiler would tell you that this function is a redefinition of:
template<typename T>
void foo(const T* a)
Cause " " is a char*, which fits perfectly to foo(T*) function. When you remove this, the compiler will try to make it work with foo(T&), which requires you to pass reference to char array that contains the string.
Compiler can't generate one function that would receive reference to char, as you are passing whole array, so it has to dereference it.