According to my understanding CRTP(Curiously Recurring Template Pattern) is used when a class is derived from a specialization of a templated-base class. So the base class can access the functionality of derived class then delegate to derived class after casting the Parameter to a derived class. Here is an example:
#include <iostream>
using namespace std;
template< class T>
class Shape2D{
public:
Shape2D(double, double);
virtual ~Shape2D();
void SetDims(double dim1, double dim2) {
static_cast<T*>(this)->SetDims(dim1, dim2);
}
double GetDim1() const;
double GetDim2() const;
double GetSurface()const;
double GetPerim()const;
};
template<class T>
Shape2D<T>::Shape2D(double dim1, double dim2) {
static_cast<T*>(this)->SetDims(dim1, dim2);
}
template<class T>
Shape2D<T>::~Shape2D() {
}
template<class T>
double Shape2D<T>::GetSurface()const {
return static_cast<const T*>(this)->GetSurface();
}
template<class T>
double Shape2D<T>::GetDim1()const {
return static_cast<const T*>(this)->GetDim1();
}
template<class T>
double Shape2D<T>::GetDim2()const {
return static_cast<const T*>(this)->GetDim2();
}
template<class T>
double Shape2D<T>::GetPerim()const {
return static_cast<const T*>(this)->GetPerim();
}
class Rectangle : public Shape2D<class Rectangle> {
public:
Rectangle(double, double);
void SetDims(double, double);
double GetDim1() const;
double GetDim2() const;
double GetSurface()const;
double GetPerim()const;
private:
double itsLength, itsWidth;
};
Rectangle::Rectangle(double len, double wid) :
itsLength(len), itsWidth(wid), Shape2D<Rectangle>(len, wid) {
}
void Rectangle::SetDims(double len, double wid) {
itsLength = len;
itsWidth = wid;
}
double Rectangle::GetDim1()const{
return itsLength;
}
double Rectangle::GetDim2()const {
return itsWidth;
}
double Rectangle::GetSurface()const {
return itsLength * itsWidth;
}
double Rectangle::GetPerim()const {
return ((itsLength * 2) + (itsWidth * 2));
}
int main() {
class Rectangle rct(7, 5);
cout << rct.GetSurface() << endl;
cout << rct.GetPerim() << endl;
cout << endl;
Shape2D<class Rectangle>* pSh2DRect =
new Shape2D<class Rectangle>(7, 5);
cout << "Surface: " << pSh2DRect->GetSurface() << endl;
cout << "Perimeter: " << pSh2DRect->GetPerim() << endl;
delete pSh2DRect;
cout << endl;
std::cin.get();
}
- I can't see any benefit above because I can achieve it without CRTP.
- I want a helpful example to clear my doubts about Static Polymorphism.
What if a derived
class
doesn't inherit from a specialization where this derived class is not the parameter of the template base class?? eg:class Parallelogram : public Shape2D<Rectangle>{ public: //... };
As you can see Parallelogram
normally inherit from Shape2D<Parallelogram>
not Rectangle
. Is it a Undefined Behavior?