Search code examples
c++overload-resolution

How is ambiguity determined in the overload resolution algorithm?


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?


Solution

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