2013-07-11 6 views
10

参照に変換演算子がある場合、この演算子はboolへの変換よりも優先されます。なぜこのようなことが起こり、どのように修正できますか?参照への変換がboolへの変換を妨げているのはなぜですか?

(それが重要ならば、私はGCC 4.5を使用しています私は、同じ振る舞いがGCC-4.7.2で発見されたことをideoneに検証。。)

次のことを想定します

class B { 
protected: 
    const int a_; 
    int b_; 
    B (int b, int a) : a_(a), b_(b) {} 
public: 
    operator bool() const { return b_ == a_; } 
}; 

class D1 : public B { 
public: 
    D1 (int b = 0, int a = 0) : B(b, a) {} 
    operator int() const { return b_; } 
}; 

class D2 : public B { 
public: 
    D2 (int b = 0, int a = 0) : B(b, a) {} 
    operator int &() { return b_; } 
}; 

その後、彼らはこのような単純なプログラムで使用されていると仮定します。

int main() { 
    if (D1 d1a = D1('a', 'a')) std::cout << "d1a\n"; 
    if (D1 d1b = D1('b', 'a')) std::cout << "d1b\n"; 
    if (D2 d2a = D2('a', 'a')) std::cout << "d2a\n"; 
    if (D2 d2b = D2('b', 'a')) std::cout << "d2b\n"; 
    return 0; 
} 

このプログラムの出力は次のとおりです。

d1a 
d2a 
d2b 

d1bは出力されていないことに注意してください。つまり、boolへの変換は、D1の場合と同じように動作しました。しかし、D2については、参照タイプへの変換がbool変換よりも優先されたようです。なぜこれが起こったのですか?チェックをifにすると、boolの変換が優先されるように、私はD2に簡単に変更できますか?

現在、D1を使用しており、割り当ての演算子を追加して参照の動作を実現しています。私にとって

+0

まあ、はい、私はおそらく私が同意これを自分自身に当てはめることができたはずですが、悪い一日を過ごすために私を罰する以外には、投票のためのより大きな理由がありますか? – jxh

答えて

9

によって、それはint&とは何の関係も持っていない場合、私は第四を交換する場合にのみd1aと出力のd2aあります、それはconst -nessの問題ですa D2、​​ではないため、非const変換演算子がより適切です。

operator const int &() const { return b_; } 

のように書くと、http://ideone.com/vPPPYVを参照してください。operator const int&は、あなたのオブジェクトのconstのバージョンを使用している場合でも、次の行は、まだあなたの期待行動につながる干渉しないことを

注意(http://ideone.com/DTE0xHを参照してください):

if (const D1 d1a = D1('a', 'a')) std::cout << "d1a\n"; 
if (const D1 d1b = D1('b', 'a')) std::cout << "d1b\n"; 
if (const D2 d2a = D2('a', 'a')) std::cout << "d2a\n"; 
if (const D2 d2b = D2('b', 'a')) std::cout << "d2b\n"; 
+1

ありがとう、それは私のために説明します。この問題を解決するには、 'bool'変換演算子の非コンスバージョンを追加します。 – jxh

+1

すばらしい答え! – Antonio

1

この

D1 d1a = D1('a', 'a'); 
D1 d1b = D1('b', 'a'); 
D2 d2a = D2('a', 'a'); 
D2 d2b = D2('b', 'a'); 
if (d1a) std::cout << "d1a\n"; 
if (d1b) std::cout << "d1b\n"; 
if (d2a) std::cout << "d2a\n"; 
if (d2b) std::cout << "d2b\n"; 

プリント

d1a 
d2a

あなたはどちらの場合も同じ名前を使用しない場合はどうなり

if (D2 d2a = D2('a', 'a')) std::cout << "d2a\n"; 
if (D2 d2a = D2('b', 'a')) std::cout << "d2b\n"; 

がありますか?

operator bool() const { return b_ == a_; } 
       /* ^^^^^ */ 
       /* vvvvv */ 
operator int &() { return b_; } 

d2aは次のとおりです。 実際

if (D2 d2b = D2('b', 'a')) std::cout << "d2b\n"; 
+0

結果は同じです(http://ideone.com/CpPXZSを参照)。私は質問を更新します。 – jxh

+0

さて、MSVC++ 11(VS12)は 'd2b'を印刷しません。 – Pixelchemist

+0

+1、私はGCC-C++とMSVC++の動作の違いが面白いと思っています。 – jxh

関連する問題