c++ - 什么是奇怪的重复模板模式 (CRTP)?

标签 c++ templates c++-faq crtp

没有引用书籍,任何人都可以通过代码示例对 CRTP 进行很好的解释吗?

最佳答案

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

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

奇怪地重复出现,不是吗? :)

现在,这给了你什么?这实际上给出了 X template 能够成为其特化的基类。

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

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 还有其他有用的用途。例如,如果你想计算你的类当前存在的所有实例,但想将这个逻辑封装在一个单独的模板中(具体类的想法非常简单 - 有一个静态变量,在 ctors 中递增,在 dtors 中递减).尝试将其作为练习!

另一个有用的示例,用于 Boost(我不确定他们是如何实现的,但 CRTP 也可以)。 假设您只想提供运算符 <为你的类(class),但自动运营商==为了他们!

你可以这样做:

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/56939863/

相关文章:

c++ - Windows 窗体 - 单实例 - 包含语句

C++ std::copy 结果不同于字符串构造函数

c++ - Debian 测试中缺少 `/usr/lib/libboost_unit_test_framework-mt.so'

C++ 事件/消息系统

c++ - 模板 模板参数

c++ - 错误 C2995 : function template has already been defined

c++ - 为什么必须在哪里放置 “template”和 “typename”关键字?

c++ - 如何实现is_pointer?

c++ - 为什么必须在哪里放置 “template”和 “typename”关键字?

c++ - 为什么模板只能在头文件中实现?