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

时间:2010-08-12 21:43:57

标签: 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_;
};

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

修改

我试过Potatoswatter(对不起lol)评论:

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

但它确实无效。

这是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’

2 个答案:

答案 0 :(得分:5)

您正尝试将SmartPtr作为模板类型参数传递给ThreadingModelSmartPtr是一个模板,而不是具体类型,继承列表中没有injected class-name

另请注意,您不能仅在任意位置使用模板参数的默认参数(§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);
        // ...
    }
};

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

答案 1 :(得分:0)

递归是正常的,因为将特化作为模板参数传递不会直接导致它被实例化。

(基本列表中的ThreadingModel<SmartPtr>只是使用“当前专业化”的ThreadingModel< SmartPtr< T, CheckingPolicy, ThreadingModel > >的简写。)

我不知道ThreadingModel应该做什么,所以我无法实现它,但它应该有一个声明形式

template< class Client > class MyThreading

并且它无法访问Client成员函数之外的MyThreading内的任何内容。如果您使用ClientClient取决于MyThreading,则会发生无限递归。