Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of operator RestrictedBool in QScopedPointer?

Tags:

c++

qt

qt5

I've been reading 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?

like image 553
jonspaceharper Avatar asked May 03 '16 19:05

jonspaceharper


1 Answers

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:

  • Chris's C++ Thoughts - Contextually converted to bool
  • Is the safe-bool idiom obsolete in C++11? - SO question
  • Very explicit operator bool - a writeup specific to QScopedPointer
like image 172
jonspaceharper Avatar answered Nov 15 '22 12:11

jonspaceharper