13

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?

jonspaceharper
  • 4,207
  • 2
  • 22
  • 42
  • 5
    I would say it is the Qt way of `explicit operator bool` (pre c++11). – Jarod42 May 03 '16 at 19:26
  • 2
    it is restricted to explicit conversions – 463035818_is_not_an_ai May 03 '16 at 19:28
  • 2
    [this](http://lists.qt-project.org/pipermail/development/2012-January/001433.html) made me find [this](http://www.artima.com/cppsource/safebool.html) which seems to explain the idea behind it – 463035818_is_not_an_ai May 03 '16 at 19:31
  • @tobi303: that does explain it, thank you. I'll accept if you or someone else wishes to write it up as an answer. – jonspaceharper May 03 '16 at 19:46
  • I should summarize if I have it correctly: `operator bool` returns an rvalue of `bool` that can be used for other operations. `RestrictedBool` is a private typedef of a pointer to `d`. Using it as the type for an operator means it can be used in an `if` statement, but not with other comparison operators. – jonspaceharper May 03 '16 at 19:54
  • it was also rather new to me (well, i heard about it but long time ago) and I didnt want to write an answer without reading it in detail. I would suggest you post your summary as an answer. – 463035818_is_not_an_ai May 03 '16 at 20:07
  • Thank you @tobi303, I did just that. – jonspaceharper May 03 '16 at 20:35

1 Answers1

9

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:

Community
  • 1
  • 1
jonspaceharper
  • 4,207
  • 2
  • 22
  • 42
  • 1
    Heh, did you say something like https://codereview.qt-project.org/#/c/158069/ ? :-) – peppe May 03 '16 at 21:41
  • Am I incorrectly assuming that the explicit bool still allows `if (foo)`? – jonspaceharper May 03 '16 at 21:48
  • Okay. I nixed the C++11 reference since I definitely need to read up on how `explicit operator bool` works. – jonspaceharper May 03 '16 at 23:42
  • See also https://stackoverflow.com/questions/6242768/is-the-safe-bool-idiom-obsolete-in-c11 and http://chris-sharpe.blogspot.it/2013/07/contextually-converted-to-bool.html – peppe May 03 '16 at 23:49
  • 2
    I've elaborated on this issue here https://www.kdab.com/explicit-operator-bool/ . – peppe May 26 '16 at 08:31