This is a C++ idiom, perhaps best expressed by the following:

template <typename T> class Base;
class Derived: public Base<Derived> {
    // stuff

This allows Base to reach into Derived's namespace and use methods without the overhead of virtual dispatch. This also allows recursive data types to be defined.


template <typename T>
class easy_comparisons {
    bool operator>(const T & rhs) {
        return rhs < *(static_cast<T *>this); // uses operator < in T's namespace

    bool operator==(const T & rhs) {
        return !(*(static_cast<T *>this) < rhs) && !(rhs < *(static_cast<T *>this));
    // other overloads for <=, >=, != ...

class some_numeric : public easy_comparisons<some_numeric> {
    bool operator<(const some_numeric & rhs) {
        // something...

The above example allows some_numeric to just define operator< and have all the necessary logic overloads needed. Similarly, it would be possible for some_numeric to define (unary) -, +=, *=, /= and have a base template that would create a division ring. This basically reduces the need for boilerplate.

Another example is for recursive datatypes:

struct null_type {};
template <typename A, typename B>
struct type_list {
    A head;
    B tail;
typedef type_list<int,
    type_list<char *,
        null_type> > > some_type_list;

It is then possible to create compile time algorithms which iterate over this structure.

Some known uses of this pattern:

  • Boost MetaProgramming Library(aka Boost.MPL), and so anything that uses it.
  • Spirit parser framework, a BNF parser that takes declarative style C++ (as the BNF) and (at compile time) generates the necessary framework to implement a full parser. Kind of like yacc/bison and C++ rolled together. A C99 compliant preprocessor has been implemented with it.
  • Boost smart_ptr; specifically shared_ptr. There is often a need for a object to pass a shared_ptr to itself (the managed equivalent of this) around. The library defines a base template class shared_ptr_from_this<> which allows the derived class to get a shared_ptr to itself.