Last updated:2026-10-12
C++ Mixin Idiom¶
Hello everyone, I am 光城. Today I am sharing one of the idioms from C++那些事: mixin
Mixins are a concept from Lisp. A mixin is a piece of a class, meaning it is intended to be combined with other classes or mixins. The difference between a regular standalone class (such as Person) and a mixin is that a mixin models some small piece of functionality (such as printing or displaying) and is not meant to be used standalone. Instead, it is meant to be combined with other classes that need that functionality (such as Person).
Therefore, the purpose of mixins is to allow something similar to multiple inheritance.
The basic form of a mixin in C++ is as follows:
or
template<typename... Super>
class Mixin : public Super... {
public:
Mixin() : Super...() {}
// ...
};
Note: all the sample code in this section is available from the Knowledge Planet.
Example 1: Scaling and Rotation¶
Suppose we want to scale, rotate, and add a border to a rectangle/square — all operations that affect its width and height; we can implement this with mixins.
First, we can define the square and the rectangle as the base classes of the mixin.
// 正方形类
class Square : public Shape {
public:
Square(int sideLength) : sideLength(sideLength) {}
int GetWidth() const override { return sideLength; }
int GetHeight() const override { return sideLength; }
private:
int sideLength;
};
// 长方形类
class Rectangle : public Shape {
public:
Rectangle(int width, int height) : width(width), height(height) {}
int GetWidth() const override { return width; }
int GetHeight() const override { return height; }
private:
int width;
int height;
};
Then use mixin subclasses to extend the functionality. For example: for a scaling mixin we can write a custom class whose width and height equal scale multiplied by the corresponding width and height.
// 缩放的Mixin
template <class Base, int ScaleX, int ScaleY>
class Scale : public Base {
public:
int GetScaledWidth() const { return Base::GetWidth() * ScaleX; }
int GetScaledHeight() const { return Base::GetHeight() * ScaleY; }
};
Scenarios like this are a perfect fit for mixins.
Usage:
Example 2: redo and undo¶
The complete example simulates redo and undo operations, so that we can switch back and forth between data. With Redoable<Undoable<Number>>, we can mix these classes together and use them.
#include <iostream>
using namespace std;
struct Number {
typedef int value_type;
int n;
void set(int v) {
n = v;
}
int get() const {
return n;
}
};
template <typename BASE, typename T = typename BASE::value_type>
struct Undoable : public BASE {
typedef T value_type;
T before;
void set(T v) {
before = BASE::get();
BASE::set(v);
}
void undo() {
BASE::set(before);
}
};
template <typename BASE, typename T = typename BASE::value_type>
struct Redoable : public BASE {
typedef T value_type;
T after;
void set(T v) {
after = v;
BASE::set(v);
}
void redo() {
BASE::set(after);
}
};
typedef Redoable<Undoable<Number>> ReUndoableNumber;
int main() {
ReUndoableNumber mynum;
mynum.set(42);
mynum.set(84);
cout << mynum.get() << '\n'; // Output: 84
mynum.undo();
cout << mynum.get() << '\n'; // Output: 42
mynum.redo();
cout << mynum.get() << '\n'; // Output: back to 84
}
Example 3: Repeated Printing¶
Here is another building-block example: repeated printing.
First, there is a class with which we can print a person's name.
class Name
{
public:
Name(std::string firstName, std::string lastName)
: firstName_(std::move(firstName))
, lastName_(std::move(lastName)) {}
void print() const
{
std::cout << lastName_ << ", " << firstName_ << '\n';
}
private:
std::string firstName_;
std::string lastName_;
};
But what if I want to print it repeatedly?
We can play it like this: use a mixin and pass the Name class in.
template<typename Printable>
struct RepeatPrint : Printable
{
explicit RepeatPrint(Printable const& printable) : Printable(printable) {}
void repeat(unsigned int n) const
{
while (n-- > 0)
{
this->print();
}
}
};
template<typename Printable>
RepeatPrint<Printable> repeatPrint(Printable const& printable)
{
return RepeatPrint<Printable>(printable);
}
Usage:
Now we get the printout repeated n times.
So which scenarios suit mixins best?
- Keeping the original class unchanged,
- Client code does not use the raw class directly; it has to wrap it in a mixin to gain the enhanced functionality,
Standard Library¶
There is a use of the mixin technique in the standard library: std::nested_exception.
std::nested_exception is a polymorphic mixin class that can capture and store the currently handled exception, allowing exceptions of arbitrary types to be nested within one another.
In the source we can see nested_exception used as the mixin base class.
References¶
https://cedanet.com.au/ceda/Xc++/$mixin/mixins-in-straight-c++.php
https://www.fluentcpp.com/2017/12/12/mixin-classes-yang-crtp/
https://stackoverflow.com/questions/18773367/what-are-mixins-as-a-concept
Related Topics¶
- C++ Avoiding the Default Constructor | C++那些事
- C++ Class Initializer List Idiom | C++那些事
- C++ Prefer Class Templates over Function Templates | C++那些事
- C++ copy-and-swap Idiom | C++那些事
- C++ Dependency Injection | C++那些事
- C++ enum class Strongly Typed Enums | C++那些事
- C++ Header-Only vs Implementation Separation | C++那些事
- C++ Lazy Evaluation Idiom | C++那些事
- C++ Lookup Table Idiom | C++那些事
- C++ Member Pointers and Type Information | C++那些事