The CRTP point should be able to get the type of the derived object without virtuality. If you do
struct B { void foo() const; } struct D : B { void foo() const; } void bar(const B& x) { x.foo(); }
then bar calls B::foo , not D::foo when passing the object D , since foo not a virtual function. If you want D::foo called, you need either virtual functions or CRTP.
The simplest form of CRTP:
template <typename> struct B { void foo() const; } struct D : B<D> { void foo() const; } template <typename T> void bar(const B<T>& x) { static_cast<const T&>(x).foo(); }
this calls D::foo() when you go to the bar a D object.
An alternative CRTP trick, which, however, forces D provide an implementation for foo ,
template <typename T> struct B { void foo() const { static_cast<const T*>(this)->foo_impl(); }
but you still need the template parameter for B (so that foo sent correctly) and therefore the bar template.
Also, if you are not using CRTP, you better have a virtual destructor that can add unwanted overhead for lightweight classes that need to be fully integrated. With CRTP, you simply write a protected destructor (private destructor + friend T in C ++ 0x).
source share