2012-01-10 3 views
2

J'apprends le cadre de Cinder. Il y a une classe Texture dans ce cadre, et il peut être utilisé comme ceci:Comment fonctionne cette conversion en bool?

Texture myImage; 
myImage.loadImage(/*...*/); 
if(myImage) 
{ 
    // draw the image. 
} 

Je suis devenu confus à ce sujet, parce que myImage est un objet. L'utiliser comme une condition n'a pas de sens pour moi. Je m'attendais à quelque chose comme myImage.exist();. Donc, je suis entré dans le code, et il se avère que Texture classe a un opérateur de conversion défini:

public: 
    //@{ 
    //! Emulates shared_ptr-like behavior 
    typedef std::shared_ptr<Obj> Texture::*unspecified_bool_type; 
    // What is this??? 
    operator unspecified_bool_type() const { return (mObj.get() == 0) ? 0 : &Texture::mObj; } 
    void reset() { mObj.reset(); } 
    //@} 

Obj est défini comme:

protected:  
    struct Obj { 
     Obj() : mWidth(-1), mHeight(-1), mCleanWidth(-1), mCleanHeight(-1), mInternalFormat(-1), mTextureID(0), mFlipped(false), mDeallocatorFunc(0) {} 
     Obj(int aWidth, int aHeight) : mInternalFormat(-1), mWidth(aWidth), mHeight(aHeight), mCleanWidth(aWidth), mCleanHeight(aHeight), mFlipped(false), mTextureID(0), mDeallocatorFunc(0) {} 
     ~Obj(); 

     mutable GLint mWidth, mHeight, mCleanWidth, mCleanHeight; 
     float   mMaxU, mMaxV; 
     mutable GLint mInternalFormat; 
     GLenum   mTarget; 
     GLuint   mTextureID; 
     bool   mDoNotDispose; 
     bool   mFlipped; 
     void   (*mDeallocatorFunc)(void *refcon); 
     void   *mDeallocatorRefcon;    
    }; 
    std::shared_ptr<Obj>  mObj; 

Je sais que operator int() const peut implictly changer l'objet int , mais comment fonctionne unspecified_bool_type? Le débogueur s'arrête à operator unspecified_bool_type() const { return (mObj.get() == 0) ? 0 : &Texture::mObj; } lorsque if(myImage) est en cours d'exécution.

Et je peux être un peu confus au sujet de la grammaire ici, qu'est-ce que

typedef std::shared_ptr<Obj> Texture::*unspecified_bool_type; 

signifie?

Et ne

void (*mDeallocatorFunc)(void *refcon); 

en Obj signifie que mDeallocatorFunc est un membre de la classe Obj, un pointeur de fonction à une fonction prototype avec: void xxx(void *)?

+1

On dirait une conjuration du « langage bool sûr » ... –

+0

@KerrekSB Je pense que je l'ai eu, il définit un opérateur de conversion qui peut convertir 'Texture' à' 'shared_ptr et le reste de la vérification est prévue par 'shared_ptr '. Mais qu'est-ce que 'typedef std :: shared_ptr Texture :: * unspecified_bool_type;' signifie ?? Y at-il une différence avec 'typedef std :: shared_ptr unspecified_bool_type;'? Je suis confus avec ce genre de gramma, en particulier le ':: *' pourriez-vous m'aider ici? Merci beaucoup. – shengy

+0

Cette chose en particulier est un pointeur-à-membre (qui n'est pas un pointeur ordinaire!), Mais au-delà je n'ai pas assez lu du code. Il y a beaucoup de manières populaires d'implémenter le SBI, donc si vous recherchez un peu vous pourriez trouver une description qui est très semblable à votre code ... –

Répondre

4

Ceci est the safe bool idiom. Il n'utilise pas simplement operator bool() parce que les conversions implicites peuvent causer toutes sortes de problèmes avec cet opérateur. Donc, à la place, il utilise un type qui est implicitement convertible en bool (comme un pointeur vers un membre) et c'est le moins dangereux possible. Heureusement, ce type de hack n'est pas requis en C++ 11 car nous pouvons écrire explicit operator bool à la place et ne pas tomber dans des conversions implicites.

+1

Pertinent: [L'idiome safe-bool est-il obsolète en C++ 11?] (Http://stackoverflow.com/q/6242768/500104) – Xeo

Questions connexes