patterncppCritical
What is the curiously recurring template pattern (CRTP)?
Viewed 0 times
curiouslythecrtptemplatepatternwhatrecurring
Problem
Without referring to a book, can anyone please provide a good explanation for CRTP (curiously recurring template pattern) with a code example?
Solution
In short, CRTP is when a class
It is curiously recurring, isn't it? :)
Now, what does this give you? This actually gives the
For example, you could make a generic singleton class (simplified version) like this
Now, in order to make an arbitrary class
However, CRTP is not necessary in this case, see as follow:
So you see? The singleton template assumes that its specialization for any type
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 `
CRTP is a wonderful thing :)
A has a base class which is a template specialization for the class A itself. E.g.template
class X{...};
class A : public X {...};It is curiously recurring, isn't it? :)
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
#include
template
class Singleton
{
public:
static T* GetInstance() {
if ( p == nullptr ) p = new T();
return p;
}
protected:
Singleton() = default;
Singleton(Singleton const &) = delete;
Singleton &operator=(const Singleton &) = delete;
private:
static T *p;
};
template
T *Singleton::p= nullptr;Now, in order to make an arbitrary class
A a singleton you should do thisclass A : public Singleton
{
friend Singleton;
private:
A() = default;
};
A *a0= A::GetInstance();However, CRTP is not necessary in this case, see as follow:
class C
{
friend Singleton;
private: C() = default;
};
C *c1= Singleton::GetInstance();So you see? The singleton template assumes that its specialization for any type
X will be inherited from singleton 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 exercise!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 `
, >=, <=` etc. And you could use these definitions for multiple classes, reusing the code!CRTP is a wonderful thing :)
Code Snippets
template <class T>
class X{...};
class A : public X<A> {...};#include <iostream>
template <class T>
class Singleton
{
public:
static T* GetInstance() {
if ( p == nullptr ) p = new T();
return p;
}
protected:
Singleton() = default;
Singleton(Singleton const &) = delete;
Singleton &operator=(const Singleton &) = delete;
private:
static T *p;
};
template <class T>
T *Singleton<T>::p= nullptr;class A : public Singleton<A>
{
friend Singleton;
private:
A() = default;
};
A *a0= A::GetInstance();class C
{
friend Singleton<C>;
private: C() = default;
};
C *c1= Singleton<C>::GetInstance();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 <
}Context
Stack Overflow Q#4173254, score: 356
Revisions (0)
No revisions yet.