Search code examples
c++c++11templatesstandardsstd

How to reference self type in default template arguments?


We have an reference_counted template and an default default_deallocator class as following:

template <class T>
class default_deallocator {
     void operator()(T* obj) {
         delete obj;
     }
};

template <class T>
class reference_counted: T
{
public:
   void retain() {ref_count++;}
   void release() {
        ref_count --;
        if (ref_count == 0) {
            delete this;
        }
   }
}

We want to add the deallocator for the reference_counted class. But we don't know how to write the default template argument, because the compiler will complain about recursive type reference.

//VS2015 says: fatal error C1202: recursive type or function dependency context too complex
template <class T, class D = default_deallocator<reference_counted<T>>>  <---
class reference_counted: T
{
public:
   void retain() {ref_count++;}
   void release() {
        ref_count --;
        if (ref_count == 0) {
            D deallocator;
            deallocator.operator()(this);
        }
   }
}

I understand this error. So the question is how to reference current class type in template default argument or other way to implement this design pattern?


Solution

  • You can use an higher-kinded type (a "template template parameter"):

    template <class T, template <typename...> class D = default_deallocator>  
    class reference_counted: T
    {
    public:
       void retain() {}
       void release() {
    
            D<reference_counted<T, D>> deallocator;
            deallocator(this);
    
       }
    };
    

    live example on wandbox