A couple days ago I found an interesting C++ construct named Curiously Recurring Template Pattern (usually known under abbreviation CRTP). From that time I have been attempting to fully understand how does this trick work.
Let's say I have following code snippet
#include <iostream>
template<class T>
struct GraphicalObject
{
void draw()
{
static_cast<T*>(this)->draw();
}
};
struct Circle : GraphicalObject<Circle>
{
void draw()
{
std::cout << "Drawing circle!" << std::endl;
}
};
struct Square : GraphicalObject<Square>
{
void draw()
{
std::cout << "Drawing square!" << std::endl;
}
};
int main(int argc, char** argv) {
Square s;
Circle c;
s.draw();
c.draw();
return 0;
}
All the "magic" behind the CRTP is obviously in the line static_cast<T*>(this)->draw(). But how does it work in detail? My understanding was following. Let's say I have the Circle c.
In case the compiler see this declaration it is a signal for him to instantiate the GraphicalObject template with argument Circle. I think that this results in creation of the struct GraphicalObject<Circle> by the compiler
struct GraphicalObject<Circle>
{
void draw()
{
static_cast<Circle*>(this)->draw();
}
};
So struct with a special version of the draw method is created. The struct GraphicalObject<Circle> forms the base struct for the Circle struct.
In the second step the instance c of the Circle struct is created i.e. the implicit constructor of the Circle is invoked. Due to the fact that the Circle is inherited from the GraphicalObject<Circle> the implicit constructor of that struct is invoked at first. This results in creation of an instance of the GraphicalObject<Circle> inside the c object in my opinion. Is it right? Then I think that the draw method declared in the Circle struct overrides the draw method declared in the GraphicalObject<Circle> struct. But this doesn't make sense for me. I would rather expect that the "specialized" version of the draw method comming from the GraphicalObject<Circle> shall not be overridden. Please can you tell me what is wrong in my understanding how the CRTP works?
You're not doing anything polymorphically in
mainwhich would demonstrate the features of CRTP. Try this instead and see what happens: