Without referring to a book, can anyone please provide a good explanation forCRTP (curiously recurring template pattern) with a code example?
- 3Read CRTP questions on SO:stackoverflow.com/questions/tagged/crtp. That might give you some idea.sbi– sbi2010-11-13 15:41:07 +00:00CommentedNov 13, 2010 at 15:41
- 114@sbi: If he does that, he'll find his own question. And that would be curiously recurring. :)Craig McQueen– Craig McQueen2013-01-08 12:37:54 +00:00CommentedJan 8, 2013 at 12:37
- 1BTW, it seems to me the term should be "curiously recursing". Am I misunderstanding the meaning?Craig McQueen– Craig McQueen2013-01-08 12:42:36 +00:00CommentedJan 8, 2013 at 12:42
- 3Craig: I think you are; it's "curiously recurring" in the sense that it was found to crop up in multiple contexts.Gareth McCaughan– Gareth McCaughan2016-04-20 15:54:23 +00:00CommentedApr 20, 2016 at 15:54
- Both incorrect. Re-occurring is unrelated to recurrence. This template pattern is recurrent, like a chicken-and-egg situation. We say that these recur. They don't recurse - that's referring to the act of traversing a recurrence.cliffordheath– cliffordheath2025-12-04 22:23:04 +00:00CommentedDec 4, 2025 at 22:23
6 Answers6
In short, CRTP is when a classA has a base class which is a template specialization for the classA itself. E.g.
template <class T> class X{...};class A : public X<A> {...};Itis curiously recurring, isn't it? :)
Now, what does this give you? This actually gives theX 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 <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;Now, in order to make an arbitrary classA a singleton you should do this
class A : public Singleton<A> { friend Singleton;private: A() = default;};A *a0= A::GetInstance();However, CRTP is not necessary in this case, see as follow:
class C { friend Singleton<C>; private: C() = default;};C *c1= Singleton<C>::GetInstance();So you see? The singleton template assumes that its specialization for any typeX will be inherited fromsingleton<X> and thus will have all its (public, protected) members accessible, including theGetInstance! 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< for your classes but automatically operator== for them!
you could do it like this:
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 <}or implement within the template scope without casting
template<class T>class Equality{ friend bool operator == (const T& op1, const T& op2) { return !(op1 < op2) && !(op2 < op1); }};Now you can use it like this
struct Apple:public Equality<Apple> { int size;};bool operator < (Apple const & a1, Apple const& a2){ return a1.size < a2.size;}Now, you haven't provided explicitly operator== forApple? 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! { }}This could seem that you would write less if you just wrote operator== forApple, but imagine that theEquality template would provide not only== but>,>=,<= etc. And you could use these definitions formultiple classes, reusing the code!
CRTP is a wonderful thing :)
16 Comments
Here you can see a great example. If you use virtual method the program will know what execute in runtime. Implementing CRTP the compiler is which decide in compile time!!! This is a great performance!
template <class T>class Writer{ public: Writer() { } ~Writer() { } void write(const char* str) const { static_cast<const T*>(this)->writeImpl(str); //here the magic is!!! }};class FileWriter : public Writer<FileWriter>{ public: FileWriter(FILE* aFile) { mFile = aFile; } ~FileWriter() { fclose(mFile); } //here comes the implementation of the write method on the subclass void writeImpl(const char* str) const { fprintf(mFile, "%s\n", str); } private: FILE* mFile;};class ConsoleWriter : public Writer<ConsoleWriter>{ public: ConsoleWriter() { } ~ConsoleWriter() { } void writeImpl(const char* str) const { printf("%s\n", str); }};3 Comments
virtual void write(const char* str) const = 0;? Though to be fair, this technique seems super helpful whenwrite is doing other work.CRTP is a technique to implement compile-time polymorphism. Here's a very simple example. In the below example,ProcessFoo() is working withBase class interface andBase::Foo invokes the derived object'sfoo() method, which is what you aim to do with virtual methods.
http://coliru.stacked-crooked.com/a/2d27f1e09d567d0e
template <typename T>struct Base { void foo() { (static_cast<T*>(this))->foo(); }};struct Derived : public Base<Derived> { void foo() { cout << "derived foo" << endl; }};struct AnotherDerived : public Base<AnotherDerived> { void foo() { cout << "AnotherDerived foo" << endl; }};template<typename T>void ProcessFoo(Base<T>* b) { b->foo();}int main(){ Derived d1; AnotherDerived d2; ProcessFoo(&d1); ProcessFoo(&d2); return 0;}Output:
derived fooAnotherDerived foo7 Comments
ProcessFoo() function.void ProcessFoo(T* b) and without having Derived and AnotherDerived actually derived it would still work. IMHO it would be more interesting if ProcessFoo did not make use of templates somehow.ProcessFoo() will work with any type that implements the interface i.e. in this case the input type T should have a method calledfoo(). Second, in order to get a non-templatizedProcessFoo to work with multiple types, you would likely end up using RTTI which is what we want to avoid. Moreover, templatized version provides you compilation time check on the interface.This is not a direct answer, but rather an example of howCRTP can be useful.
A good concrete example ofCRTP isstd::enable_shared_from_this from C++11:
A class
Tcan inherit fromenable_shared_from_this<T>to inherit theshared_from_thismember functions that obtain ashared_ptrinstance pointing to*this.
That is, inheriting fromstd::enable_shared_from_this makes it possible to get a shared (or weak) pointer to your instance without access to it (e.g. from a member function where you only know about*this).
It's useful when you need to give astd::shared_ptr but you only have access to*this:
struct Node;void process_node(const std::shared_ptr<Node> &);struct Node : std::enable_shared_from_this<Node> // CRTP{ std::weak_ptr<Node> parent; std::vector<std::shared_ptr<Node>> children; void add_child(std::shared_ptr<Node> child) { process_node(shared_from_this()); // Shouldn't pass `this` directly. child->parent = weak_from_this(); // Ditto. children.push_back(std::move(child)); }};The reason you can't just passthis directly instead ofshared_from_this() is that it would break the ownership mechanism:
struct S{ std::shared_ptr<S> get_shared() const { return std::shared_ptr<S>(this); }};// Both shared_ptr think they're the only owner of S.// This invokes UB (double-free).std::shared_ptr<S> s1 = std::make_shared<S>();std::shared_ptr<S> s2 = s1->get_shared();assert(s2.use_count() == 1);Comments
Just as note:
CRTP could be used to implement static polymorphism(which like dynamic polymorphism but without virtual function pointer table).
#pragma once#include <iostream>template <typename T>class Base{ public: void method() { static_cast<T*>(this)->method(); }};class Derived1 : public Base<Derived1>{ public: void method() { std::cout << "Derived1 method" << std::endl; }};class Derived2 : public Base<Derived2>{ public: void method() { std::cout << "Derived2 method" << std::endl; }};#include "crtp.h"int main(){ Derived1 d1; Derived2 d2; d1.method(); d2.method(); return 0;}The output would be :
Derived1 methodDerived2 method9 Comments
vtables without using CRTP. Whatvtables truly provide is using the base class (pointer or reference) to call derived methods. You should show how it is done with CRTP here.Base<>::method () isn't even called, nor do you use polymorphism anywhere.methodImpl in themethod ofBase and in derived classes namemethodImpl instead ofmethodAnother good example of using CRTP can be an implementation of observer design pattern. A small example can be constructed like this.
Suppose you have a classdate and you have some listener classes likedate_drawer,date_reminder, etc.. The listener classes (observers)should be notified by the subject classdate (observable) whenever a date change is done so that they can do their job (draw a date in someformat, remind for a specific date, etc.). What you can do is to have two parametrized base classesobserver andobservable from which you should deriveyourdate and observer classes (date_drawer in our case). For the observer design pattern implementation refer to the classic books likeGOF. Here we only need tohighlight the use of CRTP. Let's look at it.In our draft implementationobserver base class has one pure virtual method which should be called by theobservable class whenever a state change occurred,let's call this methodstate_changed. Let's look at the code of this small abstract base class.
template <typename T>struct observer{ virtual void state_changed(T*, variant<string, int, bool>) = 0; virtual ~observer() {}};Here, the main parameter that we should focus on is the first argumentT*, which is going to be the object for which a state was changed. The second parameteris going to be the field that was changed, it can be anything, even you can omit it, that's not the problem of our topic (in this case it's astd::variant of3 fields).The second base class is
template <typename T>class observable{ vector<unique_ptr<observer<T>>> observers;protected: void notify_observers(T* changed_obj, variant<string, int, bool> changed_state) { for (unique_ptr<observer<T>>& o : observers) { o->state_changed(changed_obj, changed_state); } }public: void subscribe_observer(unique_ptr<observer<T>> o) { observers.push_back(move(o)); } void unsubscribe_observer(unique_ptr<observer<T>> o) { }};which is also a parametric class that depends on the typeT* and that's the same object that is passed to thestate_changed function inside thenotify_observers function.Remains only to introduce the actual subject classdate and observer classdate_drawer.Here the CRTP pattern is used, we derive thedate observable class fromobservable<date>:class date : public observable<date>.
class date : public observable<date>{ string date_; int code; bool is_bank_holiday;public: void set_date_properties(int code_ = 0, bool is_bank_holiday_ = false) { code = code_; is_bank_holiday = is_bank_holiday_; //... notify_observers(this, code); notify_observers(this, is_bank_holiday); } void set_date(const string& new_date, int code_ = 0, bool is_bank_holiday_ = false) { date_ = new_date; //... notify_observers(this, new_date); } string get_date() const { return date_; }};class date_drawer : public observer<date>{public: void state_changed(date* c, variant<string, int, bool> state) override { visit([c](const auto& x) {cout << "date_drawer notified, new state is " << x << ", new date is " << c->get_date() << endl; }, state); }};Let's write some client code:
date c;c.subscribe_observer(make_unique<date_drawer>());c.set_date("27.01.2022");c.set_date_properties(7, true);the output of this test program will be.
date_drawer notified, new state is 27.01.2022, new date is 27.01.2022date_drawer notified, new state is 7, new date is 27.01.2022date_drawer notified, new state is 1, new date is 27.01.2022Note that using CRTP and passingthis to the notifynotify_observers function whenever a state change occurred (set_date_properties andset_date here). Allowed us to usedate* when overridingvoid state_changed(date* c, variant<string, int, bool> state) pure virtual function in the actualdate_drawer observer class, hence we havedate* c inside it (notobservable*) and for example we can call a non-virtual function ofdate* (get_date in our case)inside thestate_changed function.We could of refrain from wanting to use CRTP and hence not parametrizing the observer design pattern implementation and useobservable base class pointer everywhere. This way we could have the same effect, but in this case whenever we want to use the derived class pointer (even though not very recomendeed) we should usedynamic_cast downcasting which has some runtime overhead.
Comments
Explore related questions
See similar questions with these tags.






