Steps of Overload Resolution

suggest change

The steps of overload resolution are:

  1. Find candidate functions via name lookup. Unqualified calls will perform both regular unqualified lookup as well as argument-dependent lookup (if applicable).
  2. Filter the set of candidate functions to a set of viable functions. A viable function for which there exists an implicit conversion sequence between the arguments the function is called with and the parameters the function takes.
void f(char);          // (1)
void f(int ) = delete; // (2)
void f();              // (3)
void f(int& );         // (4)

f(4); // 1,2 are viable (even though 2 is deleted!) 
      // 3 is not viable because the argument lists don't match
      // 4 is not viable because we cannot bind a temporary to 
      //     a non-const lvalue reference
  1. Pick the best viable candidate. A viable function F1 is a better function than another viable function F2 if the implicit conversion sequence for each argument in F1 is not worse than the corresponding implicit conversion sequence in F2, and…:
3.1. For some argument, the implicit conversion sequence for that argument in `F1` is a better conversion sequence than for that argument in `F2`, or

    void f(int );  // (1)
    void f(char ); // (2)

    f(4);  // call (1), better conversion sequence

3.2. In a user-defined conversion, the standard conversion sequence from the return of `F1` to the destination type is a better conversion sequence than that of the return type of `F2`, or

    struct A 
    {
        operator int();
        operator double();
    } a;

    int i = a; // a.operator int() is better than a.operator double() and a conversion
    float f = a; // ambiguous
<!-- -->

3.3. In a direct reference binding, `F1` has the same kind of reference by `F2` is not, or

    struct A 
    {
        operator X&();  // #1
        operator X&&(); // #2
    };
    A a;
    X& lx = a;  // calls #1
    X&& rx = a; // calls #2

3.4. `F1` is not a function template specialization, but `F2` is, or

    template <class T> void f(T ); // #1
    void f(int );                  // #2

    f(42); // calls #2, the non-template

3.5. `F1` and `F2` are both function template specializations, but `F1` is more specialized than `F2`.

    template <class T> void f(T );  // #1
    template <class T> void f(T* ); // #2

    int* p;
    f(p); // calls #2, more specialized

The ordering here is significant. The better conversion sequence check happens before the template vs non-template check. This leads to a common error with overloading on forwarding reference:

struct A {
    A(A const& ); // #1
    
    template <class T>
    A(T&& );      // #2, not constrained
};

A a;
A b(a); // calls #2!
        // #1 is not a template but #2 resolves to
        // A(A& ), which is a less cv-qualified reference than #1
        // which makes it a better implicit conversion sequence

If there’s no single best viable candidate at the end, the call is ambiguous:

void f(double ) { }
void f(float ) { }

f(42); // error: ambiguous

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


Overload resolution:
* Steps of Overload Resolution

Table Of Contents
8 Arrays
11 Loops
39 Streams
51 Unions
56 Lambdas
60 SFINAE
62 RAII
67 Sorting
72 Overload resolution
84 RTTI
87 Scopes
104 Profiling
107 Recursion
117 Iteration
125 Alignment
134 Semaphore
136 Debugging
139 Mutexes
142 decltype