这个名字念起来有些拗口,先看一下代码示例:
// The Curiously Recurring Template Pattern (CRTP)
template<class T>
class Base{
// methods within Base can use template to access members of Derived
};
class Derived : public Base<Derived>{
// ...
};
这是CRTP一个最基本的形式,可以看出,将派生类作为基类的模板参数,意味基类可以访问派生类的一些内容,这也是名字中为什么会有递归两个字的原因。
下面是一些CRTP的使用示例:
静态多态
template <class T>
struct Base{
void interface(){
static_cast<T*>(this)->implementation();
}
static void static_func(){
T::static_sub_func();
}
};
struct Derived : Base<Derived>
{
void implementation(){
}
static void static_sub_func();
};
void Derived::static_sub_func(){
}
int main(){
Derived d{};
d.static_func();
return 0;
}
代码注入
template <typename T>
struct counter{
static int objects_created;
static int objects_alive;
counter(){
++objects_created;
++objects_alive;
}
counter(const counter&){
++objects_created;
++objects_alive;
}
~counter(){ // objects should never be removed through pointers of this type
--objects_alive;
}
};
template <typename T> int counter<T>::objects_created( 0 );
template <typename T> int counter<T>::objects_alive( 0 );
struct MyClass : public counter<MyClass>
{};
int main(){
MyClass h{};
{
MyClass a{};
MyClass c{};
MyClass d{};
}
return MyClass::objects_alive;
}
单例模式
#include <memory>
template <class ActualClass>
class Singleton{
public:
static ActualClass& GetInstance(){
if(p == nullptr)
p = std::unique_ptr<ActualClass>(new ActualClass);
return *p;
}
protected:
Singleton() = default;
static std::unique_ptr<ActualClass> p;
};
template <class T>
std::unique_ptr< T > Singleton<T>::p;
class A: public Singleton<A>
{
};
int main(){
auto& i = A::GetInstance();
}
最佳实践
namespace detail{
template <class T>
class Base{
public:
void interface()
{
// ...
self()->implementation();
// ...
}
private:
T* self(){
return static_cast<T*>(this);
}
// methods within Base can use template to access members of Derived
};
};
class Derived : public detail::Base<Derived>{
public:
void implementation(){
// do something
}
// ...
};
int main(){
Derived d;
d.interface();
}
C++ 库中,std::shared_ptr
中的std::enable_shared_from_this
使用了CRTP.
网友评论