Confusion about CRTP static polymorphism
c++, crtp
Solution
The thing is that the description of CRTP as "static polymorphism" is not really helpful or accurate, with regards to what CRPT is actually used for. Polymorphism is really just about having different types that fulfill the same interface or contract; how those different types implement that interface is orthogonal to polymorphism. Dynamic polymorphism looks like this:
void foo(Animal& a) { a.make_sound(); } // could bark, meow, etc
Where `Animal` is a base class providing a virtual `make_sound` method, that `Dog`, `Cat`, etc, override. Here is static polymorphism:
template <class T>
void foo(T& a) { a.make_sound(); }
And that's it. You can call the static version of `foo` on any type that happens to define a `make_sound` method, without inheriting from a base class. And the call will be resolved at compile time (i.e. you won't pay for a vtable call).
So where does CRTP fit in? CRTP is really not about interface at all, so it's not about polymorphism. CRTP is about letting you implement things more easily. What makes CRTP magical is that it can inject things directly into the interface of a type, with full knowledge of everything the derived type provides. A simple example might be:
template <class T>
struct MakeDouble {
T double() {
auto& me = static_cast<T&>(*this);
return me + me;
};
Now any class that defines an addition operator, can also be given a `double` method:
class Matrix : MakeDouble<Matrix> ...
Matrix m;
auto m2 = m.double();
CRTP is all about aiding in implementation, not interface. So don't get too hung up about the fact that it's often referred to as "static polymorphism". If you want the real canonical example on what CRTP can be used for, consider Chapter 1 of Andrei Alexandrescu's Modern C++ design. Though, take it slow :-).
Problem
I'm trying to wrap my head around the CRTP. There are some good sources around, including this forum, but I think I have some confusion about the basics of static polymorphism. Looking at the following Wikipedia entry: ``` template <class T> struct Base { void implementation() { // ... static_cast<T*>(this)->implementation(); // ... } static void static_func() { // ... T::static_sub_func(); // ... } }; struct Derived : public Base<Derived> { void implementation(); static void static_sub_func(); }; ``` I understand that this helps me to have different implementation() variants in derived classes, kinda like a compile-time virtual function. However, my confusion is that I think I cannot have functions like ``` void func(Base x){ x.implementation(); } ``` as I would with normal inheritance and virtual functions, due to Base being templated, but I would have to either specify ``` func(Derived x) ``` or use ``` template<class T> func(T x) ``` So what does CRTP actually buy me in this context, as opposed to simply shadowing/implementing the method straightforward in Derived::Base? ``` struct Base { void implementation(); }; struct Derived : public Base { void implementation(); static void static_sub_func(); }; ```