C++ TutorialBasic input/output in c++C++ AlignmentC++ Argument Dependent Name LookupC++ Arithmitic MetaprogrammingC++ ArraysC++ Atomic TypesC++ AttributesC++ autoC++ Basic Type KeywordsC++ Bit fieldsC++ Bit ManipulationC++ Bit OperatorsC++ Build SystemsC++ C incompatibilitiesC++ C++11 Memory ModelC++ Callable ObjectsC++ Classes/StructuresC++ Client server examplesC++ Common compile/linker errors (GCC)C++ Compiling and BuildingC++ Concurrency with OpenMPC++ Const CorrectnessC++ const keywordC++ Constant class member functionsC++ constexprC++ ContainersC++ Copy ElisionC++ Copying vs AssignmentC++ Curiously Recurring Template Pattern (CRTP)C++ Date and time using chrono headerC++ Debugging and Debug-prevention Tools & TechniquesC++ decltypeC++ Digit separatorsC++ EnumerationC++ ExceptionsC++ Explicit type conversionsC++ Expression templatesC++ File I/OC++ Floating Point ArithmeticC++ Flow ControlC++ Fold ExpressionsC++ Friend keywordC++ function call by value vs. call by referenceC++ Function OverloadingC++ Function Template OverloadingC++ Futures and PromisesC++ Header FilesC++ Implementation-defined behaviorC++ Inline functionsC++ Inline variablesC++ IterationC++ IteratorsC++ KeywordsC++ LambdasC++ Layout of object typesC++ Linkage specificationsC++ LiteralsC++ LoopsC++ Memory managementC++ MetaprogrammingC++ Move SemanticsC++ mutable keywordC++ MutexesC++ NamespacesC++ Non-Static Member FunctionsC++ One Definition Rule (ODR)C++ Operator OverloadingC++ operator precedenceC++ OptimizationC++ Overload resolutionC++ Parameter packsC++ Perfect ForwardingC++ Pimpl IdiomC++ PointersC++ Pointers to membersC++ PolymorphismC++ PreprocessorC++ ProfilingC++ RAII: Resource Acquisition Is InitializationC++ Random number generationC++ Recursive MutexC++ Refactoring TechniquesC++ ReferencesC++ Regular expressionsC++ Resource ManagementC++ Return Type CovarianceC++ Returning several values from a functionC++ RTTI: Run-Time Type InformationC++ Scopes

C++ Curiously Recurring Template Pattern (CRTP)

From WikiOD

A pattern in which a class inherits from a class template with itself as one of its template parameters. CRTP is usually used to provide static polymorphism in C++.

The Curiously Recurring Template Pattern (CRTP)[edit | edit source]

CRTP is a powerful, static alternative to virtual functions and traditional inheritance that can be used to give types properties at compile time. It works by having a base class template which takes, as one of its template parameters, the derived class. This permits it to legally perform a static_cast of its this pointer to the derived class.

Of course, this also means that a CRTP class must always be used as the base class of some other class. And the derived class must pass itself to the base class.


Let's say you have a set of containers that all support the functions begin() and end(). The standard library's requirements for containers require more functionality. We can design a CRTP base class that provides that functionality, based solely on begin() and end():

#include <iterator>
template <typename Sub>
class Container {
    // self() yields a reference to the derived type
    Sub& self() { return *static_cast<Sub*>(this); }
    Sub const& self() const { return *static_cast<Sub const*>(this); }

    decltype(auto) front() {
      return *self().begin();

    decltype(auto) back() {
      return *std::prev(self().end());

    decltype(auto) size() const {
      return std::distance(self().begin(), self().end());

    decltype(auto) operator[](std::size_t i) {
      return *std::next(self().begin(), i);

The above class provides the functions front(), back(), size(), and operator[] for any subclass which provides begin() and end(). An example subclass is a simple dynamically allocated array:

#include <memory>
// A dynamically allocated array
template <typename T>
class DynArray : public Container<DynArray<T>> {
    using Base = Container<DynArray<T>>;

    DynArray(std::size_t size)
      : size_{size},
    { }

    T* begin() { return data_.get(); }
    const T* begin() const { return data_.get(); }
    T* end() { return data_.get() + size_; }
    const T* end() const { return data_.get() + size_; }

    std::size_t size_;
    std::unique_ptr<T[]> data_;

Users of the DynArray class can use the interfaces provided by the CRTP base class easily as follows:

DynArray<int> arr(10);
arr.front() = 2;
arr[2] = 5;
assert(arr.size() == 10);

Usefulness: This pattern particularly avoids virtual function calls at run-time which occur to traverse down the inheritance hierarchy and simply relies on static casts:

DynArray<int> arr(10);
DynArray<int>::Base & base = arr;
base.begin(); // no virtual calls

The only static cast inside the function begin() in the base class Container<DynArray<int>> allows the compiler to drastically optimize the code and no virtual table look up happens at runtime.

Limitations: Because the base class is templated and different for two different DynArrays it is not possible to store pointers to their base classes in an type-homogenous array as one could generally do with normal inheritance where the base class is not dependent on the derived type:

class A {};
class B: public A{};

A* a = new B;

CRTP to avoid code duplication[edit | edit source]

The example in Visitor Pattern provides a compelling use-case for CRTP:

struct IShape
    virtual ~IShape() = default;

    virtual void accept(IShapeVisitor&) const = 0;

struct Circle : IShape
    // ...        
    // Each shape has to implement this method the same way
    void accept(IShapeVisitor& visitor) const override { visitor.visit(*this); }
    // ...

struct Square : IShape
    // ...    
    // Each shape has to implement this method the same way
    void accept(IShapeVisitor& visitor) const override { visitor.visit(*this); }
    // ...

Each child type of IShape needs to implement the same function the same way. That's a lot of extra typing. Instead, we can introduce a new type in the hierarchy that does this for us:

template <class Derived>
struct IShapeAcceptor : IShape {
    void accept(IShapeVisitor& visitor) const override {
        // visit with our exact type
        visitor.visit(*static_cast<Derived const*>(this));

And now, each shape simply needs to inherit from the acceptor:

struct Circle : IShapeAcceptor<Circle>
    Circle(const Point& center, double radius) : center(center), radius(radius) {}
    Point center;
    double radius;

struct Square : IShapeAcceptor<Square>
    Square(const Point& topLeft, double sideLength) : topLeft(topLeft), sideLength(sideLength) {}    
    Point topLeft;
    double sideLength;

No duplicate code necessary.