It’s often used to realize static polymorphism.
Use cases are:
- Policy-based design
- Curiously recurring template pattern
- Barton–Nackman trick
In general you have the benefits from dynamic polymorphism, without the extra runtime costs of virtual functions. But it’s only useful if the concrete type can be determined at compile time.