2010-07-07 7 views
21

Szukałem, w jaki sposób std::tr1::shared_ptr<> zapewnia zdolność do rzucania do bool. Muszę złapać w przeszłości, kiedy próbuje stworzyć inteligentne wskaźnik, który może być lanego do bool jako rozwiązanie trywialne, tjW jaki sposób shared_ptr <> bezpiecznie zezwalają na casting do bool?

operator bool() { 
    return m_Ptr!=0; 
} 

zwykle kończy się niejawnie rzutować na typ wskaźnika (przypuszczalnie przez typ promocji), co jest ogólnie niepożądane. Zarówno implementacja boost, jak i Microsoft wydają się wykorzystywać sztuczkę polegającą na rzutowaniu na unspecified_bool_type(). Czy ktoś może wyjaśnić, jak działa ten mechanizm i jak zapobiega niejawnemu rzutowaniu na typ wskaźnika bazowego?

+0

Wszystkie świetne odpowiedzi, dzięki. Dobrze być w stanie nadać mu nazwę - wcześniej nie natknąłem się na bezpieczny kod. –

Odpowiedz

31

Technika opisana w pytaniu to safe bool idiom.

Od C++ 11 ten idiom nie jest już potrzebny. Nowoczesne rozwiązanie tego problemu jest użycie słowa kluczowego explicit od operatora:

explicit operator bool() { 
    return m_Ptr != nullptr; 
} 
+0

Och, wiedziałem o bezpiecznym idiomie boolowym i niedawno odkryłem operatory konwersji "explicite", ale nie wiedziałem o tym, co to 'lil '' null_ptr'. Dzięki :) –

3

Zwykle to, co zwraca, to wskaźnik elementu. Wskaźniki członków mogą być traktowane jak bool, ale nie obsługują wielu niejawnych konwersji, które wykonuje.

4

Sztuczka działa w ten sposób. Zdefiniować to wszystko wewnątrz inteligentnego typu wskaźnika (w tym przypadku shared_ptr):

private: 

    struct Tester 
    { 
    Tester(int) {} // No default constructor 
    void dummy() {} 
    }; 

    typedef void (Tester::*unspecified_bool_type)(); 

public: 

    operator unspecified_bool_type() const 
    { 
    return !ptr_ ? 0 : &Tester::dummy; 
    } 

ptr_ jest natywny wskaźnik wewnątrz inteligentnej klasy wskaźnika.

Jak widać, unspecified_bool_type jest typedef dla typu, do którego nie można uzyskać dostępu z zewnętrznego kodu, ponieważ Tester jest prywatną strukturą. Ale kod wywołujący może użyć tej (niejawnej) konwersji do typu wskaźnika i sprawdzić, czy jest on pusty czy nie. Które, w C++, może być używane jako wyrażenie bool.

+0

Co się dzieje z '## ModelId'? – kennytm

+0

@KennyTM: Przepraszam, po prostu to usunąłem. – Gorpik

+1

Musisz podać implementacje '! =' I '==' dla 'Tester :: unspecified_bool_type' lub pozwolisz na bezsensowne porównania między wystąpieniami klasy do kompilacji. –

Powiązane problemy