Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use template template class argument as parameter

Tags:

c++

templates

Modern C++ Design gives the following example:

template <class T> struct EnsureNotNull
{
    static void Check(T*& ptr)
    {
      if (!ptr) ptr = GetDefaultValue();
    }
};

template
<
   class T,
   template <class> class CheckingPolicy = EnsureNotNull,
   template <class> class ThreadingModel
>
class SmartPtr
  : public CheckingPolicy<T>
  , public ThreadingModel<SmartPtr>
{
...
  T* operator->()
  {
    typename ThreadingModel<SmartPtr>::Lock guard(*this);
    CheckingPolicy<T>::Check(pointee_);
    return pointee_;
  }
private:
  T* pointee_;
};

I couldn't figure how ThreadingModel template would be constructed in a fashion that It could accept SmartPtr as parameter, in my mind some crazy recursion is going to happen. How can this be possible?

Edit:

I've tried Potatoswatter (sorry lol) comment:

template <class SmartPtr> struct SingleThreadingModel
{
  class Lock
  {
    public: 
      Lock(SmartPtr&)
      {
      }
  };
};

but it did'nt worked.

here is the error that gcc is giving me:

main.cpp:28:35: error: type/value mismatch at argument 1 in template parameter list for ‘template<class> class ThreadingModel’
main.cpp:28:35: error:   expected a type, got ‘SmartPtr’
like image 312
scooterman Avatar asked Aug 12 '10 21:08

scooterman


1 Answers

You are trying to pass SmartPtr as a template type argument to ThreadingModel. SmartPtr however is a template, not a concrete type, and the injected class-name is not available in the inheritance list.

Also note that you can't just use default arguments for template parameters in arbitrary positions (§14.1/11):

If a template-parameter has a default template-argument, all subsequent template-parameters shall have a default template-argument supplied.

Your code with those issues fixed:

template
<
  class T,
  template <class> class ThreadingModel,
  template <class> class CheckingPolicy = EnsureNotNull
>
class SmartPtr
  : public CheckingPolicy<T>
  , public ThreadingModel<SmartPtr<T, ThreadingModel, CheckingPolicy> > 
//                         ^ .... now passing a concrete class .... ^
{
    T* operator->() {
        // the following use of SmartPtr is fine as it is the injected class-name:
        typename ThreadingModel<SmartPtr>::Lock guard(*this);
        // ...
    }
};

Note that while Modern C++ Design is an excellent book, it can't replace a good basic book on templates like Vandevoorde/Josuttis.

like image 188
Georg Fritzsche Avatar answered Sep 24 '22 13:09

Georg Fritzsche