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’
答案 0 :(得分:5)
您正尝试将SmartPtr
作为模板类型参数传递给ThreadingModel
。 SmartPtr
是一个模板,而不是具体类型,继承列表中没有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
内的任何内容。如果您使用Client
而Client
取决于MyThreading
,则会发生无限递归。