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’
                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.
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