CRTP for static polymorphism
But, what if you still don't want to pay the price for polymorphism? One possibility is to switch to static polymorphism. The curiously recurring template pattern (CRTP) is one of the older template techniques popularized by Jim Coplien in the 90s. CRTP defines a kind of mix-in, which adds some functionality to a given class but doesn't use virtual functions for that, as in the following example:
template<class T>
class OracleBase
{
// within base we can use members of derived class T!
int whatsTheAnswer() const
{
return static_cast<T>(this)->getAnswer() * 2;
}
};
class Oracle1: public OracleBase<Oracle1>
{
int getAnswer() const { return 22; }
} o1;
class Oracle2: public OracleBase<Oracle2>
{
int getAnswer() const { return 21; }
} o2;
// now use the base class
template<typename T>
void answerFrom(const OracleBase<T>& base)
{
std::cout << "answer: " << base.whatsTheAnswer() << '\n';
}
answerFrom(o1);
answerFrom(o2);
We see that, instead of overriding a virtual function, we call the method of a derived class directly by casting to the subclass and using its interface. So, we spared one pointer indirection, but was it worth it? Well, on the positive side, it could enable the inlining of that function by the compiler, hence enabling further optimizations.
As always, we should use this technique only when calls over the vtable were identified as the bottleneck. And it isn't a real replacement of dynamic polymorphism as we cannot store such objects in a single container!
Allow me to make a digression here that is not performance-related: a really cool use case for CRTP is the grafting of new functionality onto existing classes, as is illustrated in the following example, which adds an equality operator to struct X, assuming the less-than operator is defined:
template <class Derived>
class Eq {};
template <class Derived>
bool operator == (const Eq<Derived>& lhs, const Eq<Derived>& rhs)
{
Derived const& d1 = static_cast<Derived const&>(lhs);
Derived const& d2 = static_cast<Derived const&>(rhs);
return !(d1 < d2) && !(d2 < d1);
}
struct X: public Eq<X> { int size; };
bool operator < (const X& lhs, const X& rhs)
{
return lhs.size < rhs.size;
}
A concrete example of CRTP used in that way in C++11 standard is the std::enable_shared_form_this<T> class—look it up!