The CRTP Idiom
Curiously recurring template pattern.
The CRTP Idiom is a free C++ Academy lesson on CoddyKit. This is lesson 1 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the C++ Academy learning path, and your progress syncs across the web and the CoddyKit app. The C++ Academy course includes 4 lessons in total.
What Is CRTP?
The Curiously Recurring Template Pattern (CRTP) is a C++ idiom where a class Derived inherits from a template base instantiated with Derived itself.
- Shape:
class Derived : public Base<Derived> - The base learns its derived type at compile time
template <typename T>
class Base {};
class Derived : public Base<Derived> {};The Core Mechanism
Inside the base, you can static_cast the this pointer to the derived type. Because the derived type is a template parameter, this is a fully compile-time cast with no runtime cost.
#include <iostream>
template <typename T>
class Base {
public:
void interface() {
static_cast<T*>(this)->implementation();
}
};
class Derived : public Base<Derived> {
public:
void implementation() { std::cout << "Derived impl\n"; }
};
int main() {
Derived d;
d.interface();
return 0;
}Why "Curiously Recurring"?
The name comes from the apparent paradox: the base class refers to the derived class, which is not yet fully defined when the base template is written.
- It works because templates are only instantiated when used
- By instantiation time,
Derivedis a complete type
A First Real Use
CRTP lets a base provide reusable functionality that calls back into the derived class. Here the base supplies a print() that delegates to the derived name().
#include <iostream>
#include <string>
template <typename T>
struct Named {
void print() {
std::cout << static_cast<T*>(this)->name() << "\n";
}
};
struct Cat : Named<Cat> {
std::string name() { return "Cat"; }
};
int main() {
Cat c;
c.print();
return 0;
}No Virtual Tables
Unlike runtime polymorphism, CRTP needs no virtual keyword and no vtable pointer in each object. Dispatch is resolved entirely at compile time.
- Smaller objects (no hidden vptr)
- Calls can be inlined
Counting Instances
A classic CRTP application is an object counter. Each derived class gets its own static counter automatically.
#include <iostream>
template <typename T>
struct Counter {
static inline int count = 0;
Counter() { ++count; }
~Counter() { --count; }
};
struct Widget : Counter<Widget> {};
int main() {
Widget a, b;
std::cout << Widget::count << "\n";
return 0;
}Each Derived Gets Its Own State
Because Counter<Widget> and Counter<Gadget> are distinct template instantiations, each has an independent static count. This separation is impossible with a single non-template base.
#include <iostream>
template <typename T>
struct Counter {
static inline int count = 0;
Counter() { ++count; }
};
struct A : Counter<A> {};
struct B : Counter<B> {};
int main() {
A a1, a2;
B b1;
std::cout << A::count << " " << B::count << "\n";
return 0;
}The static_cast Is Safe Here
The downcast inside the base is safe only if every object of type Base<T> truly is a T. CRTP guarantees this by construction, since T is the class that inherits.
- Never instantiate
Base<Wrong>for an unrelated class
Comparison Operators via CRTP
You can synthesize a full set of comparison operators from a single operator< by deriving from a comparison helper.
#include <iostream>
template <typename T>
struct Comparable {
friend bool operator>(const T& a, const T& b) { return b < a; }
friend bool operator==(const T& a, const T& b) { return !(a < b) && !(b < a); }
};
struct Num : Comparable<Num> {
int v;
Num(int x) : v(x) {}
friend bool operator<(const Num& a, const Num& b) { return a.v < b.v; }
};
int main() {
std::cout << (Num(3) > Num(2)) << "\n";
return 0;
}Protected Constructor Guard
To prevent accidental misuse of the base, give it a protected constructor so only derived classes can create it.
#include <iostream>
template <typename T>
class Base {
protected:
Base() = default;
public:
void run() { static_cast<T*>(this)->step(); }
};
class Job : public Base<Job> {
public:
void step() { std::cout << "step\n"; }
};
int main() {
Job j;
j.run();
return 0;
}CRTP in Standard Libraries
CRTP appears throughout real C++ libraries.
std::enable_shared_from_this<T>uses it- Many expression-template math libraries (Eigen) rely on it
- Ranges and iterator helpers use similar patterns
Recognizing the shape X : Base<X> helps you read advanced code.
Quick Check
Test your understanding of the CRTP shape.
Recap
You learned the CRTP idiom.
Derived : Base<Derived>gives the base its concrete type- A
static_cast<T*>(this)enables compile-time dispatch - No vtable, smaller objects, inlinable calls
- Used for counters, comparison mixins, and library helpers
Learn C++ with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 51
- Lessons
- 203
Frequently Asked Questions
Is the “The CRTP Idiom” lesson free?
Yes — any 3 lessons of the C++ Academy learning path, including “The CRTP Idiom”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The C++ Academy course includes 4 lessons in total.
What will I learn in “The CRTP Idiom”?
Curiously recurring template pattern. You practise C++ Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C++ Academy?
No prior experience is required. C++ Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 1 of 4.
How long does the “The CRTP Idiom” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C++ Academy lesson?
Yes. Every C++ Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The CRTP Idiom
- Static Polymorphism
- Mixins with CRTP
- When to Use CRTP