Reputation: 859
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?
Upvotes: 0
Views: 240
Reputation: 4449
You're not doing anything polymorphically in main
which would demonstrate the features of CRTP. Try this instead and see what happens:
template <typename T>
void drawObject(GraphicalObject<T>& obj) {
obj.draw();
}
int main() {
Square s;
Circle c;
s.draw();
c.draw();
drawObject(s); // what happens here?
GraphicalObject<Circle>& c_ref = c;
drawObject(c_ref); // what happens here?
}
Upvotes: 1