使用模板模板类参数作为参数

sco*_*man 5 c++ templates

Modern C++ Design提供了以下示例:

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_;
};
Run Code Online (Sandbox Code Playgroud)

我无法想象ThreadingModel模板将如何以一种它可以接受SmartPtr作为参数的方式构建,在我看来会发生一些疯狂的递归.这怎么可能?

编辑:

我试过Potatoswatter(抱歉lol)评论:

template <class SmartPtr> struct SingleThreadingModel
{
  class Lock
  {
    public: 
      Lock(SmartPtr&)
      {
      }
  };
};
Run Code Online (Sandbox Code Playgroud)

但它确实没用.

这是gcc给我的错误:

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’
Run Code Online (Sandbox Code Playgroud)

Geo*_*che 5

您正尝试将SmartPtr模板类型参数传递给ThreadingModel.SmartPtr但是它是一个模板,而不是具体类型,并且在继承列表中没有注入的类名.

另请注意,您不能仅在任意位置使用模板参数的默认参数(§14.1/ 11):

如果template-parameter具有默认的template-argument,则所有后续模板参数都应提供默认的template-argument.

修复了这些问题的代码:

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);
        // ...
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意,虽然Modern C++ Design是一本很好的书,但它不能取代像Vandevoorde/Josuttis这样的模板上的好基础书.