2010-07-07 14 views
21

Estaba investigando cómo std::tr1::shared_ptr<> proporciona la capacidad de transmitir a bool. He quedó atrapado en el pasado cuando se trata de crear un puntero inteligente que se puede lanzar a bool como la solución trivial, es decir¿Cómo shared_ptr <> permite de forma segura el casting bool?

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

por lo general termina siendo implícitamente convertible al tipo de puntero (presumiblemente por la promoción Tipo), que en general es indeseable. Tanto el impulso como las implementaciones de Microsoft parecen usar un truco que involucra la conversión a un unspecified_bool_type(). ¿Alguien puede explicar cómo funciona este mecanismo y cómo previene la conversión implícita al tipo de puntero subyacente?

+0

Todas las respuestas excelentes, gracias. Es bueno poder ponerle nombre: no había encontrado el idioma de bool seguro antes. –

Respuesta

31

La técnica descrita en la pregunta es safe bool idiom.

A partir de C++ 11, ese modismo ya no es necesario. La solución moderna al problema es utilizar la palabra clave explicit del operador:

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

Oh, yo sabía de la expresión de bool seguro y descubrí recientemente los operadores de conversión 'explícitos', pero no sabía acerca de esta pequeña cosa' 'null_ptr'. Gracias :) –

3

Por lo general, lo que devuelve es un puntero de miembro. Los punteros de miembro se pueden tratar como bool pero no admiten muchas de las conversiones implícitas que hace bool.

4

El truco funciona de esta manera. Se define todo esto dentro de su tipo puntero inteligente (en este caso, 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_ es el puntero nativa dentro de la clase puntero inteligente.

Como se puede ver, es un unspecified_bool_typetypedef a un tipo que no se puede acceder por cualquier código externo, ya que Tester es una estructura privada. Pero el código de llamada puede usar esta conversión (implícita) a un tipo de puntero y verificar si es nulo o no. Que, en C++, se puede usar como una expresión bool.

+0

¿Qué pasa con el '## ModelId'? – kennytm

+0

@KennyTM: Lo siento, simplemente eliminé eso. – Gorpik

+1

Debe proporcionar implementaciones de '! =' Y '==' para 'Tester :: unspecified_bool_type' o permitirá comparaciones sin sentido entre instancias de la clase para compilar. –

Cuestiones relacionadas