2013-07-11 6 views
10

Sembra che se ho un operatore di conversione su un riferimento, questo operatore avrà la precedenza su una conversione in un bool. Perché succede e come posso risolverlo?Perché la conversione al riferimento interferisce con la conversione in bool?

(. Se è importante, io sto usando GCC 4.5 ho verificato sul Ideone che lo stesso comportamento è trovato con GCC-4.7.2.)

assumere i seguenti:

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_; } 
}; 

Poi, assumono vengono utilizzati in un programma semplice come questo:

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; 
} 

L'output di questo programma è:

d1a 
d2a 
d2b 

Nota che d1b non è nell'output, il che significa che la conversione in bool ha funzionato come previsto per D1. Tuttavia, per D2, sembra che la conversione al tipo di riferimento abbia avuto la precedenza sulla conversione bool. Perché è successo? C'è una semplice modifica che posso apportare a D2 per consentire alla conversione bool di avere la precedenza nel controllo if?

Attualmente sto utilizzando D1 e aggiungo un operatore di assegnazione per ottenere il comportamento di un riferimento.

+0

Ebbene sì, sono d'accordo che probabilmente avrei dovuto essere in grado di individuarlo da solo, ma c'è una ragione più sostanziale per il voto negativo oltre a punirmi per me avere una brutta giornata? – jxh

risposta

9

In realtà, non ha nulla a che fare con int&, è una questione di const -ness:

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

d2a è a D2, non a const D2, quindi l'operatore di conversione non const è più adatto. Se si scrive come

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

si otterrà il comportamento previsto, vedere http://ideone.com/vPPPYV.

Nota che operator const int& non interferiranno anche se si utilizza il const versioni di oggetti, le seguenti righe sarebbe ancora provocare il vostro comportamento previsto (vedi 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

Grazie, questo lo spiega per me. La correzione consiste nell'aggiungere una versione non '' concreta' dell'operatore di conversione 'bool'. – jxh

+1

Risposta fantastica! – Antonio

1

Questo

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"; 

stampe

d1a 
d2a

per me.

Hai

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

Cosa succede se non si utilizza lo stesso nome in entrambi i casi? C'è solo d1a e d2a nell'output se sostituire il 4 ° se per

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

Il risultato è lo stesso (vedere http://ideone.com/CpPXZS). Aggiornerò la domanda – jxh

+0

Ok, beh ... MSVC++ 11 (VS12) non stampa 'd2b'. – Pixelchemist

+0

+1, trovo interessante la differenza di comportamento tra GCC-C++ e MSVC++. – jxh

Problemi correlati