過載決議的步驟

過載解析的步驟是:

  1. 通過名稱查詢查詢候選函式。非限定呼叫將執行常規非限定查詢以及依賴於引數的查詢(如果適用)。

  2. 將候選函式集過濾為一組可行的函式。一個可行的函式,在呼叫函式的引數和函式所使用的引數之間存在隱式轉換序列。

    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
    
  3. 選擇最有可行的候選人。如果 F1 中每個引數的隱式轉換序列不比 F2 中相應的隱式轉換序列差,則可行函式 F1 是比另一個可行函式 F2 更好的函式,並且……:

    3.1。對於某些引數,F1 中該引數的隱式轉換序列是比 F2 中的引數更好的轉換序列,或者

    void f(int );  // (1)
    void f(char ); // (2)
    
    f(4);  // call (1), better conversion sequence
    

    3.2。在使用者定義的轉換中,從 F1 返回到目標型別的標準轉換序列是比 F2 的返回型別更好的轉換序列,或者

    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。在直接引用繫結中,F1F2 具有相同型別的引用,或者

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

    3.4。F1 不是一個功能模板專業化,但 F2 是,或

    template <class T> void f(T ); // #1
    void f(int );                  // #2
    
    f(42); // calls #2, the non-template
    

    3.5。F1F2 都是功能模板專業化,但 F1F2 更專業。

    template <class T> void f(T );  // #1
    template <class T> void f(T* ); // #2
    
    int* p;
    f(p); // calls #2, more specialized
    

這裡的訂購很重要。在模板與非模板檢查之前進行更好的轉換序列檢查。這導致轉發引用上的過載常見錯誤:

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

如果最後沒有單一的最佳可行候選人,那麼這個呼叫是不明確的:

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

f(42); // error: ambiguous