什么是奇怪的重复模板模式(CRTP)? [英] What is the curiously recurring template pattern (CRTP)?

查看:141
本文介绍了什么是奇怪的重复模板模式(CRTP)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人都可以用代码示例为 CRTP 提供一个很好的解释?

请不要请我参考一本书,我已经做了有书和引用他们,但我通常找到你们提出的解释/例子,在理解概念和许多其他重要的微妙的东西,一个概念更合适和实用。

Can anyone please provide a good explanation for CRTP with a code example?
Please do not ask me to refer a book, I already do have the books and refer them but I usually find the explanations/examples that you guys come up with at SO much more suitable and practical in understanding the concept and lot of other important subtle things that go with a concept.

推荐答案

简而言之,CRTP是A类有一个基类,它是A类本身的模板专用化。例如

In short, CRTP is when a class A has a base class which is a template specialization for the class A itself. E.g.

template <class T> class X{...};
class A : public X<A> {...};

这是奇怪的重现,不是吗? :)

It is curiously recurring, isn't it? :)

现在,这给了你什么?这实际上给了X模板作为其专门化的基类的能力。

Now, what does this give you? This actually gives the X template the ability to be a base class for its specializations.

例如,您可以像这样创建一个通用单例类(简化版本)。

For example, you could make a generic singleton class (simplified version) like this

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成为单例,你应该这样做

Now, in order to make an arbitrary class A a singleton you should do this

class A: public Singleton<A>
{
   //Rest of functionality 
};

所以你看到了?单例模板假定其对任何类型X的专门化将继承自 singleton< X> ,并且因此将具有所有其(公共的,受保护的)成员可访问,包括 GetInstance !还有CRTP的其他有用的用途。例如,如果你想计算你的类当前存在的所有实例,但是想要将这个逻辑封装在一个单独的模板中(对于一个具体的类,思想是非常简单的 - 有一个静态变量,在ctors中递增,在dtors中递减)。尝试做一个锻炼!

So you see? The singleton template assumes that its specialization for any type X will be inherited from singleton<X> and thus will have all its(public, protected) members accessible, including the GetInstance! There are other useful uses of CRTP. For example, if you want to count all instances that currently exist for your class, but want to encapsulate this logic in a separate template (the idea for a concrete class is quite simple - have a static variable, increment in ctors, decrement in dtors). Try to do it as an excercise!

另一个有用的例子,boost(我不知道他们是如何实现的,但CRTP也会)。
想象一下,你想提供只有operator<

Yet another useful example, for boost(I am not sure how they have implemented it, but CRTP will do too). Imagine you want to provide only operator < for your classes but automatically operator == for them!

你可以这样做:

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, isnit 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提供明确的operator ==但你有它!您可以写

now, you haven't provided explicitly operator == for apple? But you have it! You can write

int main()
{
    Apple a1;
    Apple a2; 

    a1.size = 10;
    a2.size = 10;
    if(a1 == a2) //the compiler won't complain! 
    {
    }
}

如果你只是为苹果编写operator ==,但是想象平等模板不仅会提供==,但是>,> =,< =等。你可以使用这些定义 multiple 类,重用代码!

This could seem that you would write less if you just wrote operator == for Apple, but imagine that the Equality template would provide not only == but >, >=, <= etc. And you could use these definitions for multiple classes, reusing the code!

CRTP是一件奇妙的事情:) HTH

CRTP is a wonderful thing :) HTH

这篇关于什么是奇怪的重复模板模式(CRTP)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆