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)
您正尝试将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这样的模板上的好基础书.