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

5

《现代C++设计》给出了以下示例:

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_;
};

我无法想象如何构建ThreadingModel模板以使其能够接受SmartPtr作为参数,在我看来,某些疯狂的递归将会发生。这怎么可能呢?

编辑:

我尝试了Potatoswatter(抱歉哈哈)的评论:

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’

啊,是的。模板模板参数。这是最令人困惑的事情之一。 - John Dibling
2
你的新代码看起来很好。你遇到了什么错误,是在哪里?此外,番茄泼击器听起来会制造一大堆麻烦,我尽量避免这样做。 - Potatoswatter
2个回答

5
您正在尝试将SmartPtr作为模板类型参数传递给ThreadingModel。然而,SmartPtr是一个模板,不是一个具体的类型,并且注入类名在继承列表中不可用。

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

如果一个模板参数有一个默认的模板参数,则所有后续的模板参数都必须提供一个默认的模板参数。

修复了这些问题后,您的代码如下:

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);
        // ...
    }
};

请注意,虽然现代C++设计是一本优秀的书,但它不能替代像Vandevoorde/Josuttis这样的好的基础模板书。

没错。我已经从Loki下载了源代码,并注意到类定义中没有ThreadingModel。 - scooterman

0

递归是可以的,因为将特化作为模板参数传递并不会直接导致其被实例化。

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

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

的声明
template< class Client > class MyThreading

它无法访问MyThreading成员函数之外的Client任何内容。如果你使用Client并且Client依赖MyThreading,就会发生无限递归。


Potato,你能提供一下ThreadingModel声明应该如何实现吗?我在这里尝试了很多种方法,但都没有成功。 - scooterman
嗯,尝试过了。无论使用还是不使用Client insite类都没有起作用。请注意,在示例中它构建了一个保护程序,并将其作为参数传递,因此应该可以工作。 - scooterman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接