Very specifically, the CRTP can be used instead of a base class with virtual functions to implement the template method pattern without virtual function call overhead.
With virtual functions, the TMP looks like this:
class ProvidesMethod {
protected:
void Method() {
// do something
Part1();
// do something else
Part2();
// do something final
}
private:
virtual void Part1() = 0;
virtual void Part2() = 0;
};
class ExposesMethod : private ProvidesMethod {
public:
using ProvidesMethod::Method;
private:
void Part1() {
// first part implementation
}
void Part2() {
// second part implementation
}
};
With the CRTP, it looks like this:
template <typename Derived>
class ProvidesMethod {
protected:
void Method() {
// do something
self().Part1();
// do something else
self().Part2();
// do something final
}
private:
Derived& self() { return *static_cast<Derived*>(this); }
const Derived& self() const { return *static_cast<const Derived*>(this); }
};
class ExposesMethod : private ProvidesMethod<ExposesMethod> {
public:
using ProvidesMethod<ExposesMethod>::Method;
private:
friend class ProvidesMethod<ExposesMethod>;
void Part1() {
// first part implementation
}
void Part2() {
// second part implementation
}
};