2010-08-12 133 views
5

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

我想不出怎样的ThreadingModel模板会以一种方式构成,即它可以接受的SmartPtr为参数,在我心中一些疯狂的递归将会发生。这怎么可能?

编辑:

我试过Potatoswatter(不好意思笑)评论:

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

但它did'nt工作。

这里是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’ 
+0

啊,是的。模板模板参数。有史以来最令人困惑的事情之一。 – 2010-08-12 21:59:52

+2

你的新代码看起来很好。你得到什么错误,在哪里?另外,一个Tomatoswatter听起来会让它变得一团糟,我试图避免这样做。 – Potatoswatter 2010-08-13 01:09:04

回答

5

您试图通过SmartPtr作为模板类型参数为ThreadingModel。然而,SmartPtr是一个模板,而不是具体的类型,并且injected class-name在继承列表中不可用。

还要注意的是,你不能只使用默认参数在任意位置模板参数(§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

+0

有道理。我已经下载了Loki的源代码,并注意到类定义中没有ThreadingModel。 – scooterman 2010-08-13 13:19:29

0

递归是可以的,因为通过专业化作为模板参数并不直接导致它被实例化。

ThreadingModel<SmartPtr>在基地名单只是针对ThreadingModel< SmartPtr< T, CheckingPolicy, ThreadingModel > >简写,它使用了“当前专业化。”)

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

template< class Client > class MyThreading 

的声明,并不能内部ClientMyThreading成员函数访问任何东西。如果您使用ClientClient取决于MyThreading,则发生无限递归。

+0

马铃薯,你能提供如何执行ThreadingModel的声明吗?我在这里尝试了很多方法,但都没有成功。 – scooterman 2010-08-12 23:04:56

+0

嗯,试过了。它没有使用或不使用客户端insite类。请注意,在该示例中,它构建了一个传递这个参数的警卫,因此它应该可以工作。 – scooterman 2010-08-12 23:54:43