CRTP (Curiously Recurring Template Pattern) Tutorial
Introduction
The Curiously Recurring Template Pattern (CRTP) is a C++ idiom where a class template is derived from itself. This pattern is used to achieve static polymorphism, which allows the compiler to resolve function calls at compile-time, providing performance benefits and potentially better optimization opportunities.
Basic Concept
In CRTP, a class Derived
inherits from a template class Base
, where Base
is parameterized by Derived
itself. This creates a recursive inheritance relationship.
Example:
template <typename T> class Base { public: void interface() { static_cast<T*>(this)->implementation(); } }; class Derived : public Base<Derived> { public: void implementation() { // Derived-specific implementation } };
Benefits of CRTP
CRTP provides several benefits:
- Static Polymorphism: The function calls are resolved at compile-time, which avoids the overhead of virtual function calls.
- Code Reusability: Common functionality can be implemented in the base class and reused in derived classes.
- Compile-time Checking: Errors can be caught at compile-time rather than runtime.
Example: Static Polymorphism
Let's consider a scenario where we want different derived classes to implement a common interface. CRTP allows us to achieve this without virtual functions:
Example:
#include <iostream> template <typename T> class Base { public: void interface() { static_cast<T*>(this)->implementation(); } }; class Derived1 : public Base<Derived1> { public: void implementation() { std::cout << "Derived1 implementation" << std::endl; } }; class Derived2 : public Base<Derived2> { public: void implementation() { std::cout << "Derived2 implementation" << std::endl; } }; int main() { Derived1 d1; Derived2 d2; d1.interface(); d2.interface(); return 0; }
Derived1 implementation Derived2 implementation
Advanced Usage: Mixins
CRTP can be extended to create mixin classes, allowing multiple inheritance of behavior. This can be particularly useful for composing different functionalities.
Example:
#include <iostream> template <typename T> class Mixin1 { public: void feature1() { static_cast<T*>(this)->feature1_impl(); } }; template <typename T> class Mixin2 { public: void feature2() { static_cast<T*>(this)->feature2_impl(); } }; class Combined : public Mixin1<Combined>, public Mixin2<Combined> { public: void feature1_impl() { std::cout << "Feature 1 implementation" << std::endl; } void feature2_impl() { std::cout << "Feature 2 implementation" << std::endl; } }; int main() { Combined c; c.feature1(); c.feature2(); return 0; }
Feature 1 implementation Feature 2 implementation
Conclusion
The Curiously Recurring Template Pattern (CRTP) is a powerful technique in C++ for achieving static polymorphism and code reuse. It leverages template inheritance to allow derived classes to implement specific behavior while avoiding the overhead of virtual function calls. By understanding and applying CRTP, developers can write more efficient and maintainable C++ code.