How is ambiguity determined in the overload resolution algorithm?

后端 未结 3 1987
南方客
南方客 2021-01-30 12:34

I\'m trying to understand the overloading resolution method.

Why is this ambiguous:

void func(double, int, int, double) {}
void func(int, double, double,         


        
相关标签:
3条回答
  • 2021-01-30 13:00

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

    0 讨论(0)
  • 2021-01-30 13:02

    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.

    0 讨论(0)
  • 2021-01-30 13:13

    Ambiguity is determined by the ranking:

    1. Exact match: no conversion required, lvalue-to-rvalue conversion, qualification conversion, user-defined conversion of class type to the same class
    2. Promotion: integral promotion, floating-point promotion
    3. 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.

    0 讨论(0)
提交回复
热议问题