Reputation: 3260
I am watching this cpp lightning talk video there it shows this snippet of code at 0:37
template<typename T, typename cleanup = QScopedPointerDeleter<T>>
class QScopedPointer{
typedef T *QScopedPointer::*RestrictedBool; // how does this work?
//why not QScopedPointer<T> since QScopedPointer is a template?
public:
inline operator RestrictedBool() const
{
return isNull()? Q_NULLPTR : &QScopedPointer::d;
}
inline bool isNull() const{ return !d;}
protected:
T *d;
};
I am having a hard time understanding typedef T *QScopedPointer::*RestrictedBool;
, what does it mean?
I have created a similar class F
, but it doesn't compile, what's the difference between the two typedefs in class QScopedPointer
and in class F
?
template<typename T>
class F{
typedef T *F::*bool;
public:
operator bool(){return true;}
};
Upvotes: 4
Views: 193
Reputation: 523204
typedef T *QScopedPointer::*RestrictedBool;
This can be made clear a little bit when we move the stars around:
typedef T* QScopedPointer::* RestrictedBool;
// ^~~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~
// the type the alias
In C++11 we would write this we more clearly as
using RestrictedBool = T* QScopedPointer::*;
RestrictedBool
here is declared as a type alias of T* QScopedPointer::*
. So typedef T *F::bool
fails because you can't redefine bool
:) The name is quite misleading because the type is not really a boolean.
The type T* QScopedPointer::*
is a pointer-to-member type. This type here accepts any T*
members in the QScopedPointer<T, cleanup>
class, so e.g. we see
class QScopedPointer {
operator RestrictedBool() const {
// ^~~~~~~~~~~~~~
// this function returns a `RestrictedBool` = `T* QScopedPointer::*`
return isNull()? Q_NULLPTR : &QScopedPointer::d;
// ^~~~~~~~~~~~~~~~~~
// and this expression has type `T* QScopedPointer::*`
}
T *d;
// ^~~
// the `d` member has type `T*` in the `QScopedPointer` class.
};
why not
QScopedPointer<T>
sinceQScopedPointer
is a template?
Inside QScopedPointer<T, cleanup>
, the class name QScopedPointer
can be used in place of QScopedPointer<T, cleanup>
. This is called locally declared names. See C++ template name used without template parameter for detail.
Upvotes: 6