2012-01-03 26 views
3

在回答this question時,我發現在成員和非成員運營商之間的rvalue引用的重載解決方案有一個有趣的區別。成員和非成員運營商臨時選擇const超載的差異

給定兩個非成員運算符,一個將左參數作爲const傳遞,另一個作爲非常量,GCC 4.4.3和MSVC2010在用右值調用時選擇const版本。

但是,給定兩個成員操作符,一個const和一個非const,兩個編譯器都選擇非const的版本。

我假設兩個編譯器都符合這個標準,所以我很好奇爲什麼在成員和非成員之間的const重載解析之間存在這種差異。請賜教:)

下面是一些代碼來說明的區別:

#include <iostream> 

class C { 
public: 
    C(int i) { } 

    /* 
    C operator<<(C const &rhs) { 
     std::cout << "member non-const" << std::endl; 
     return *this; 
    } 
    C operator<<(C const &rhs) const { 
     std::cout << "member const" << std::endl; 
     return *this; 
    } 
    //*/ 
}; 

C operator<<(C &lhs, C const &rhs) { 
    std::cout << "non-member non-const" << std::endl; 
    return lhs; 
} 
C operator<<(C const &lhs, C const &rhs) { 
    std::cout << "non-member const" << std::endl; 
    return lhs; 
} 

int main() { 
    // Will print: 
    // "non-member const" when member operators are commented out 
    // "member non-const" when members are uncommented 
    C(5) << 6; 
} 

回答

2

右值不能綁定到引用到非const,所以只有參考給const自由功能超載是可行的: operator<<(C(5), 6);

這不適用於成員運算符,它只是C(5).operator<<(6),而C對象不是函數參數。你必須說static_cast<const C &>(C(5)) << 6在那裏得到const版本,因爲它是this的常量,區分了兩個成員操作符重載。

在存在成員函數和自由函數運算符的情況下,首選成員函數,因此將所有這些放在一起解釋觀察到的行爲。

+0

請注意,標準中的特殊規則允許在類類型的臨時對象上調用非const成員函數。在C++ 11中,這可以通過'&'ref-qualifier輕鬆禁用。 – Xeo 2012-01-03 13:24:30

+0

不錯,快速回答,謝謝!我很習慣使用非成員操作員,我忘記了成員操作員使用這個(即不是參考)作爲他們的lhs。 – zennehoy 2012-01-03 13:28:00

+0

@Xeo:謝謝 - 事實上,C++ 11對'this'有ref-qualifiers,但我不知道任何編譯器在這一點上實現它們。 – 2012-01-03 14:57:39