Reputation: 30842
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
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
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
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