jonspaceharper
jonspaceharper

Reputation: 4367

What is the purpose of operator RestrictedBool in QScopedPointer?

I read through the code for QScopedPointer and came across something that I haven't been able to make sense of.

Here's the pertinent code from QScopedPointer on code.qt.io:

template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
class QScopedPointer
{
    typedef T *QScopedPointer:: *RestrictedBool;
public:
...
#if defined(Q_QDOC)
    inline operator bool() const
    {
        return isNull() ? Q_NULLPTR : &QScopedPointer::d;
    }
#else
    inline operator RestrictedBool() const
    {
        return isNull() ? Q_NULLPTR : &QScopedPointer::d;
    }
#endif
...
inline bool isNull() const
{
    return !d;
}
...
protected:
    T *d;

I understand the preprocessor definition that makes QDoc think QScopedPointer has an operator bool instead of operator RestrictedBool. What I don't understand it what purpose RestrictedBool serves and how it does it. For example, a simpler implementation is:

inline operator bool() const
{
    return !isNull();
}

In short: What's happening here? Why is operator RestrictedBool underhandedly returning the address of d and why does it exist in the first place instead of operator bool?

Upvotes: 13

Views: 770

Answers (1)

jonspaceharper
jonspaceharper

Reputation: 4367

This is an implementation of the Safe Bool Idiom, explained here.

The naive implementation:

inline operator bool() const
{
    return !isNull();
}

returns an rvalue of bool that can be implicitly used for other operations, e.g.

QScopedPointer<Foo> foo(nullptr);
int i = 1;
if (foo < i)
    ...

is valid code.

Summary: RestrictedBool is a private typedef of a pointer to the type of d. Using it as the return type for an operator means it can be used in an if statement (if (foo)), but cannot be used with other operators.

Note: C++11 allows the use of explicit operator bool, which eliminates the need for the Safe Bool Idiom in C++11 or later code. An implementation for QScopedPointer in C++11 might look like this:

explicit operator bool() const
{
    return !isNull();
}

Thank you to tobi303 and Jarod42 for providing the basis for this answer.

Further reading regarding C++11 and the Safe Bool Idiom:

Upvotes: 9

Related Questions