40781

How does this conversion to bool work?

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 *)?

Answer1:

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.

Recommend

  • Getting rid of ANSI escape characters when viewing ri in (Mac)Vim
  • Is there a parser equivalent of 'fragment' marking in ANTLR4?
  • C++ Single function pointer for all template instances
  • Building Qt project for C++11 standard
  • C++ friend class std::vector
  • Wrong labels when plotting a time series pandas dataframe with matplotlib
  • Error in installing package: fatal error: stdlib.h: no such file or directory
  • Simple linked list-C
  • Android application: how to use the camera and grab the image bytes?
  • C: Incompatible pointer type initializing
  • QLineEdit password safety
  • AES padding and writing the ciphertext to a disk file
  • VS2008 Enable C++ Exception with SEH
  • Can I have the cursor start on a particular column by default in jqgrid's edit mode?
  • Rearranging Cells in UITableView Bug & Saving Changes
  • Circular dependency while pushing http interceptor
  • Linker errors when using intrinsic function via function pointer
  • Free memory of cv::Mat loaded using FileStorage API
  • Trying to get generic when generic is not available
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • Getting Messege Twice Using IMvxMessenger
  • Change div Background jquery
  • How to get Windows thread pool to call class member function?
  • Bitwise OR returns boolean when one of operands is nil
  • EntityFramework adding new object to nested object collection
  • XCode 8, some methods disappeared ? ex: layoutAttributesClass() -> AnyClass
  • Checking variable from a different class in C#
  • Easiest way to encapsulate a HTML5 webpage into an android app?
  • Django query for large number of relationships
  • Busy indicator not showing up in wpf window [duplicate]
  • costura.fody for a dll that references another dll
  • Why is Django giving me: 'first_name' is an invalid keyword argument for this function?
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • How can I use `wmic` in a Windows PE script?
  • failed to connect to specific WiFi in android programmatically
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?
  • How to push additional view controllers onto NavigationController but keep the TabBar?
  • How can I use threading to 'tick' a timer to be accessed by other threads?