C++ Academy · Lesson

The CRTP Idiom

Curiously recurring template pattern.

Lesson 1 of 413 steps

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, Derived is 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
Free to start

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

  1. The CRTP Idiom
  2. Static Polymorphism
  3. Mixins with CRTP
  4. When to Use CRTP
← Back to C++ Academy