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
?
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With