2

I'm learning the Cinder framework. There is a class Texture in this framework, and it can be used like this:

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

I got confused about this, because myImage is an object. Using it as a condition doesn't make sense to me. I expected something like myImage.exist();. So I stepped through the code, and it turns out that Texture class has a conversion operator defined:

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 is defined as:

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;

I know that operator int() const can implictly change the Object to int, but how is unspecified_bool_type working? The debugger stops at operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &Texture::mObj; } when if(myImage) is executing.

And I may be a little confused about the grammar here, what does

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

mean?

And does

void (*mDeallocatorFunc)(void *refcon); 

in Obj mean that mDeallocatorFunc is a member of Class Obj, a function pointer to a function with prototype: void xxx(void *)?

Michael Kristofik
  • 34,290
  • 15
  • 75
  • 125
shengy
  • 9,461
  • 4
  • 37
  • 61
  • 1
    Looks like some incantation of the "safe bool idiom"... – Kerrek SB Jan 10 '12 at 19:26
  • @KerrekSB I think I got it, it defines a conversion operator which can convert `Texture` to `shared_ptr` and the rest of the checking is provided by `shared_ptr`. But what does `typedef std::shared_ptr Texture::*unspecified_bool_type;` mean?? is there any difference with `typedef std::shared_ptr unspecified_bool_type;` ? I'm confused with this kind of gramma, especially the `::*` could you help me out here? thank you very much. – shengy Jan 10 '12 at 19:32
  • That thing in particular is a pointer-to-member (which isn't an ordinary pointer!), but beyond that I haven't read enough of the code. There are many popular ways to implement the SBI, so if you search a bit you might find a description that is very similar to your code... – Kerrek SB Jan 10 '12 at 19:35
  • @KerrekSB so after `typedef std::shared_ptr Texture::*unspecified_bool_type;` if I write `unspecified_bool_type var;` then var means a pointer to shared_ptr and it must point to a member of Texture? – shengy Jan 10 '12 at 19:39
  • @shengy : Specifically, given `typedef std::shared_ptr Texture::*unspecified_bool_type;`, `unspecified_bool_type` is a pointer to a data member of `Texture` of type `std::shared_ptr`. Returning a pointer of this type does not ever instantiate a new `shared_ptr<>`. – ildjarn Jan 10 '12 at 21:36

1 Answers1

4

This is the safe bool idiom. It doesn't use simply operator bool() because implicit conversions can cause all kinds of trouble with that operator. So instead it uses a type that is implicitly convertible to bool (like a pointer to member) and that is the least dangerous possible.

Luckily this sort of hack is not required in C++11 because we can write explicit operator bool instead and not fall prey to implicit conversions.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • 1
    Relevant: [Is the safe-bool idiom obsolete in C++11?](http://stackoverflow.com/q/6242768/500104) – Xeo Jan 10 '12 at 23:41