2012-01-03 7 views
3

this questionと答えると、rvalueの過負荷解決に興味深い違いがありました。一時的にメンバーと非メンバーのオペレータのconst-overloadの選択の差

2つの非メンバー演算子(constとして左パラメータを渡し、非constとして1つ)を指定すると、GCC 4.4.3とMSVC2010の両方がrvalueで呼び出されたときにconstバージョンを選択します。

しかし、constと非constの2つのメンバ演算子がある場合、両方のコンパイラは非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

右辺値が参照ツーnonconstに結合することができないので、唯一のフリー機能のリファレンス・ツー・constのオーバーロードは実行可能です。 operator<<(C(5), 6);

これはmember-operatorには適用されません。単純にC(5).operator<<(6)であり、C -objectは関数の引数ではありません。 2つのメンバ演算子のオーバーロードを区別するのはthisの定数なので、そこにconstバージョンを取得するには、static_cast<const C &>(C(5)) << 6と言う必要があります。

メンバー関数と自由関数演算子の両方が存在する場合、メンバー関数が優先されるため、これらをまとめて観測される動作を説明します。

+0

標準の特別な規則では、非constメンバ関数をクラス型の一時的な型で呼び出すことができます。 C++ 11では、これを '&' ref-qualifierで簡単に無効にすることができます。 – Xeo

+0

ニース、クイックアンサー、ありがとう!私はメンバー以外の演算子を使用するのに慣れています。メンバー演算子がlhとしてこれを使用することを忘れています(つまり、参照ではありません)。 – zennehoy

+0

@ Xeo:ありがとう、確かに、C++ 11には 'this'のref-qualifierがありますが、現時点では実装しているコンパイラは分かりません。 –

関連する問題