C++ Academy · Lesson

Mixins with CRTP

Compose behavior at compile time.

Lesson 3 of 413 steps

Mixins with CRTP is a free C++ Academy lesson on CoddyKit. This is lesson 3 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 a Mixin?

A mixin is a small reusable unit of behavior you compose into a class. With CRTP, mixins add functionality at compile time while still calling into the host class.

A Simple Mixin

This mixin adds a print_twice method that relies on the host providing value().

#include <iostream>

template <typename T>
struct PrintTwice {
    void print_twice() const {
        auto v = static_cast<const T*>(this)->value();
        std::cout << v << " " << v << "\n";
    }
};

struct Box : PrintTwice<Box> {
    int value() const { return 7; }
};

int main() {
    Box{}.print_twice();
    return 0;
}

Composing Multiple Mixins

You can inherit from several CRTP mixins at once, stacking independent behaviors onto one class.

#include <iostream>

template <typename T>
struct Loggable {
    void log() const { std::cout << "log: " << static_cast<const T*>(this)->id() << "\n"; }
};

template <typename T>
struct Resettable {
    void reset() { static_cast<T*>(this)->set(0); }
};

struct Device : Loggable<Device>, Resettable<Device> {
    int v = 5;
    int id() const { return v; }
    void set(int x) { v = x; }
};

int main() {
    Device d;
    d.log();
    d.reset();
    d.log();
    return 0;
}

Mixins Add State Too

A mixin can carry its own data members, which become part of the composed object layout.

#include <iostream>

template <typename T>
struct Tagged {
    int tag = 0;
    void set_tag(int t) { tag = t; }
    int get_tag() const { return tag; }
};

struct Item : Tagged<Item> {
    const char* name = "item";
};

int main() {
    Item it;
    it.set_tag(42);
    std::cout << it.name << " " << it.get_tag() << "\n";
    return 0;
}

Mixin vs Plain Inheritance

A CRTP mixin differs from ordinary inheritance because the base can call down into the derived class. Ordinary base classes cannot call methods that only exist on the derived type without virtuals.

Policy-Based Design

Mixins enable policy-based design: behaviors are selected at compile time by choosing which mixins to inherit, similar to how std::vector takes an allocator policy.

Ordering and Layout

When stacking mixins, the order of bases affects construction order and object layout. Keep mixins independent so order does not matter for correctness.

  • Construct in declaration order of bases
  • Avoid mixins that depend on each other

Adding an Equality Mixin

Here a mixin synthesizes operator!= from the host equality.

#include <iostream>

template <typename T>
struct EqualityMixin {
    friend bool operator!=(const T& a, const T& b) { return !(a == b); }
};

struct P : EqualityMixin<P> {
    int x;
    P(int v) : x(v) {}
    friend bool operator==(const P& a, const P& b) { return a.x == b.x; }
};

int main() {
    std::cout << (P(1) != P(2)) << "\n";
    return 0;
}

Conditional Mixins

You can include a mixin only when a condition holds by combining inheritance with std::conditional, choosing between a real mixin and an empty one.

Empty Base Optimization

Mixins that hold no data members benefit from the Empty Base Optimization: the compiler allocates zero extra bytes for them, so stacking many stateless mixins is free in terms of size.

#include <iostream>

template <typename T>
struct A {};
template <typename T>
struct B {};

struct C : A<C>, B<C> {
    int x;
};

int main() {
    std::cout << (sizeof(C) == sizeof(int)) << "\n";
    return 0;
}

When to Reach for Mixins

Mixins shine when many classes need the same orthogonal behaviors (logging, counting, comparison). They keep each behavior in one place and compose without runtime cost.

Quick Check

Test your grasp of CRTP mixins.

Recap

You learned to build mixins with CRTP.

  • Mixins compose orthogonal behavior at compile time
  • They can call down into the host and carry state
  • Stateless mixins are free thanks to Empty Base Optimization
  • Great for logging, comparison, counting policies
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 “Mixins with CRTP” lesson free?

Yes — any 3 lessons of the C++ Academy learning path, including “Mixins with CRTP”, 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 “Mixins with CRTP”?

Compose behavior at compile time. 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 3 of 4.

How long does the “Mixins with CRTP” 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