不参考书籍,任何人都可以通过代码示例为CRTP
提供一个很好的解释吗?
最佳答案
简而言之,CRTP是当A
类具有基类时,该基类是A
类本身的模板专用化。例如。
template <class T>
class X{...};
class A : public X<A> {...};
奇怪地反复出现,不是吗? :)
现在,这给你什么?实际上,这使
X
模板能够成为其特化的基类。例如,您可以像这样创建一个通用的单例类(简化版本)
template <class ActualClass>
class Singleton
{
public:
static ActualClass& GetInstance()
{
if(p == nullptr)
p = new ActualClass;
return *p;
}
protected:
static ActualClass* p;
private:
Singleton(){}
Singleton(Singleton const &);
Singleton& operator = (Singleton const &);
};
template <class T>
T* Singleton<T>::p = nullptr;
现在,为了使任意类
A
为单例,您应该这样做class A: public Singleton<A>
{
//Rest of functionality for class A
};
所以你看?单例模板假定其对任何类型
X
的专门化都将从singleton<X>
继承,因此可以访问其所有(公共(public), protected )成员,包括GetInstance
! CRTP还有其他有用的用途。例如,如果您要计算您的类当前存在的所有实例,但想将此逻辑封装在单独的模板中(具体类的想法很简单-拥有一个静态变量,ctor中的增量,dtor中的减量)。尝试做为练习!对于Boost,还有另一个有用的示例(我不确定他们是如何实现的,但是CRTP也会这样做)。
想象一下,您只想为您的类提供运算符
<
,而为它们自动提供运算符==
!您可以这样做:
template<class Derived>
class Equality
{
};
template <class Derived>
bool operator == (Equality<Derived> const& op1, Equality<Derived> const & op2)
{
Derived const& d1 = static_cast<Derived const&>(op1);//you assume this works
//because you know that the dynamic type will actually be your template parameter.
//wonderful, isn't it?
Derived const& d2 = static_cast<Derived const&>(op2);
return !(d1 < d2) && !(d2 < d1);//assuming derived has operator <
}
现在您可以像这样使用它
struct Apple:public Equality<Apple>
{
int size;
};
bool operator < (Apple const & a1, Apple const& a2)
{
return a1.size < a2.size;
}
现在,您还没有为
==
提供显式运算符Apple
?但是你有!你可以写int main()
{
Apple a1;
Apple a2;
a1.size = 10;
a2.size = 10;
if(a1 == a2) //the compiler won't complain!
{
}
}
如果您只为
==
编写运算符Apple
,这似乎可以减少编写代码,但可以想象Equality
模板不仅可以提供==
,还可以提供>
,>=
,<=
等。并且您可以将这些定义用于多个类,重用代码!CRTP是一件了不起的事情:) HTH
关于c++ - 什么是好奇重复模板模式(CRTP)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57736062/