the_mandrill
the_mandrill

Reputation: 30842

How does shared_ptr<> safely allow casting to bool?

I was looking into how std::tr1::shared_ptr<> provides the ability to cast to bool. I've got caught out in the past when trying to create a smart pointer that can be casted to bool as the trivial solution, ie

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

usually ends up being implicitly castable to the pointer type (presumably by type promotion), which is generally undesirable. Both the boost and Microsoft implementations appear to use a trick involving casting to an unspecified_bool_type(). Can anyone explain how this mechanism works and how it prevents implicit casting to the underlying pointer type?

Upvotes: 21

Views: 9147

Answers (3)

JoeG
JoeG

Reputation: 13182

The technique described in the question is the safe bool idiom.

As of C++11, that idiom is no longer necessary. The modern solution to the problem is to use the explicit keyword on the operator:

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

Upvotes: 35

Gorpik
Gorpik

Reputation: 11028

The trick works like this. You define all this inside your smart pointer type (in this case, 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_ is the native pointer inside the smart pointer class.

As you can see, unspecified_bool_type is a typedef to a type that cannot be accessed by any external code, since Tester is a private struct. But calling code can use this (implicit) conversion to a pointer type and check whether it is null or not. Which, in C++, can be used as a bool expression.

Upvotes: 5

sbi
sbi

Reputation: 224069

Usually what it returns is a member pointer. Member pointers can be treated like a bool but don't support many of the implicit conversions which bool does.

Upvotes: 3

Related Questions