My view on static polymorphism through the CRTP pattern (source code included).

The CRTP pattern is one of those obscure and esotheric things in C++, yet very useful. One of its uses is as static polymorphism. Traditional polymorphism uses virtual functions (and, under the hood, pointers, indirections, and a table of pointers, the so called vtable), which turns the objects more complex. Static polymorphism resolves its calls in compilation time, instead of running time, as the dynamic polymorphism does. So there isn’t virtual functions nor performance penalties.

In this post I’ll try to explain you the pattern towards its use as static interface using static polymorphism.

How did I involve myself in this creepy thing? I’m embedded systems programmer, and as so, I program devices with very small ammount of resources, for example 128KB of memory program, and 16 KB of volatile memory. At the same time, polymorphism is a great mechanism to be used when programming. But using it will consume the scarce resources, so I found the CRTP pattern

What is the CRTP pattern?

What is the core of the CRTP pattern? To derive a base class from a derived class. Told you, it’s esotheric. It means, you write a derived class that in turn will create its base class (mind blowing in 3, 2, 1, …). Although it seems a classic inheritance mechanism, it isn’t. You’ll be creating a new complete class with every new object.

How it works?

Let’s see its structure (we’ll see the details later):

template<typename T>
class BaseClass
{
public:
   void Print(); // it uses the method greetings() from the derived classes
};

// IMPLEMENTATION 1:

class SubClass1 : public BaseClass<SubClass1>
{
public:
   void greetings();
};

// IMPLEMENTATION 2:

class SubClass2 : public BaseClass<SubClass2>
{
public:
   void greetings();
};

// The client:

int main()
{
   SubClass1 subClass1;
   SubClass2 subClass2;

   subClass1.Print();
   subClass2.Print();
}

You must notice first that the base class has been templatized! And pay attention to the fact that the derived classes derives from the base class indicating from which base class it’s going to be derived. This step is the most important.

Also notice that in this example the method BaseClass::Print() in the base class is going to call functions (SubClassX::greetings()) from the derived classes. Is that possible with regular inheritance?

BE AWARE: As the base clase is templatized the compiler does nothing when found its declaration, it means, it doesn’t exist (yet).

But when the compiler founds a derived class:

class SubClass1 : public BaseClass<SubClass1>{...};

it’s compelled to create a base class of type SubClass1. Please note that I wrote «a base class», not «the base class»; in this pattern there’s not such thing as «the base class».

And when the compiler founds another derived class:

class SubClass2 : public BaseClass<SubClass2>{…};

then it creates another base class, this time of type SubClass2.

In a regular programming we would have 3 classes at this point: the base class and two derived ones. However, in this pattern we only have two classes: SubClass1 and SubClass2.

The details

Now it’s time to review the easiest part of the pattern: the implementation details. I mean it! The hardest part of the pattern is to understand that a derived class creates its base class. When you are done with it, then you’re ready to move on.

Let’s start with the derived classes, as they don’t have anything special beyond their declarations:

// IMPLEMENTATION 1:

class SubClass1 : public BaseClass<SubClass1>
{
public:
   void greetings()
   {
      std::cout << "Hello world\n";
   }
};

// IMPLEMENTATION 2:

class SubClass2 : public BaseClass<SubClass2>
{
public:
   void greetings()
   {
      std::cout << "Hola mundo\n";
   }
};

The methods SubClass1::greetings() prints out the message «Hello world«, whilst SubClass2::greetings() prints out the message «Hola mundo» (which means «Hello world» in spanish). In this example the polymorphic method is BaseClass::Print().

Now let’s review the base class:

template<typename T>
class BaseClass
{
public:

   void Print()
   {
      std::cout << "I'm the polymorphic method! -> ";

      T& p = static_cast<T&>( *this );
      p->greetings();
   }

protected:

   BaseClass() = default;
   // hide the constructors from the clients

};

The method BaseClass::Print() is the polymorphic method. Line 10 downcasts the base class so it is able to access the methods from the derived classes. As the correct call must be resolved in compile time (that’s why we’re here), then it’s needed to use the static casting. The constructor has been set protected so the clients don’t create objects from it. The derived class’ constructor takes the needed arguments and passes them to the base class, if any.

Finally, the client’s code:

int main()
{
   SubClass1 subClass1;
   SubClass2 subClass2;

   subClass1.Print();   // should print "Hello world"
   subClass2.Print();   // should print "Hola mundo"
}

With output:

$ ./crtp.out 
I'm the polymorphic object! -> Hello world
I'm the polymorphic object! -> Hola mundo
$ 

We can see from the output that the polymorphic method is called first, as it should, and it, in turn, calls the correct greeting!

(Static) Interfaces

As I said I got into this pattern because I was looking a cheap way to implement interfaces (cheap for the processor, it’s been intelectually expensive). CRTP pattern can be used to implement (static) interfaces.

You’ve noticed in the previous code that a method from the base class (the polymorphic one) calls methods from the derived classes. It’s a kind of dependency injection, if you don’t mind the term. But what if you need an abstract interface to be used as a contract? If using dynamic polymorphism then it’s straightforward to name the polymorphic objects; sadly, it’s not true in static polymorphism. If you name all methods the same, then the compiler will take those from the derived classes:

template<typename T>
class BaseClass
{
public:
   void Print();   // won't be called ever
};

class SubClass1 : public BaseClass<SubClass1>
{
public:
   void Print();   // it's the one that will be called
};

int main()
{
   SubClass1 subClass1;
   subClass1.Print();   // it calls the Print() method from the derived class directly!
}

It’s output is:

$ ./salida.out 
Hello world
$ 

In order to implement interfaces we must name the methods from the derived class slightly different from those from the base class. So it’s mandatory to set a naming convention, for example the polymorphic methods names should start with capital letter, while the implementation methods names should start width a single underscore, followed by the name of the method it’s implementing, or whatever other convention makes sense to you or to your project:

template<typename T>
class BaseClass
{
public:

   void Print()
   {
      std::cout << "I'm still the polymorphic method! -> ";

      T& p = static_cast<T&>( *this );
      p._Print();
   }
};

class SubClass1 : public BaseClass<SubClass1>
{
public:
   void _Print()
   {
      std::cout << "Hello world\n";
   }
};

int main()
{
   SubClass1 subClass1;
    subClass1.Print();
}

It’s output is:

$ ./salida.out 
I'm the polymorphic method! -> Hello world
I'm the polymorphic method! -> Hola mundo
$ 

What’s next

I can’t enumerate all of the CRTP pattern use cases. I begin with it because I was working (and I’m right now) with a real time operating system for microcontrollers, FreeRTOS. It’s written in plain C, and I wanted to objectify some of its features, and the only way was through polymorphism. Of course I didn’t want to pay the costs of dynamic polymorphism, so the CRTP pattern came out to the rescue. Here you can see how I used this pattern to objectify the task creation in such operating system.

Bibliography and source code

Here you can download the examples of this post, or you can clone them:

git clone https://fjrg76@bitbucket.org/fjrg76/crtp_examples.git
  • CRTP. From Wikipedia.
  • CRTP. Great explanation.
  • CRTP. Another great explanation.

Hope you’ve enjoy this post. If so, you can consider to subscribe to my blog or write me a line.

4 respuestas a «My view on static polymorphism through the CRTP pattern (source code included).»

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

A %d blogueros les gusta esto: