Allanqunzi
Allanqunzi

Reputation: 3260

How does this typedef work?

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

Answers (1)

kennytm
kennytm

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> since QScopedPointer 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

Related Questions