CRTP
CRTP 全名 Curiously Recurring Template Pattern ,又被稱作 F-bound polymorphism ,F-bound quantification 中的一種形式。故事要先從型態轉型開始。
A general function for all derived class
常常會遇到從同一個 base class 繼承下來許多子類別,而會希望對這些子類別有一些通用的函數可以呼叫。這時在 runtime 才能得知子類別,但是想要把它轉型時無從下手。這裡以 Shape 與可能繼承 Shape 這個 class 的子類別來做舉例:
class Shape {} class Square : public Shape {} class Circle : public Shape {} class Octagon : public Shape {} void copyShape (Shape *shape) { Shape copied = new ????(*shape); // we don't know the derived type }
這時一般會寫在 base class 寫一個 virtual function ,並要求繼承的子類別都去 override 。如下:
class Shape { public: virtual Shape* clone () const = 0; }; class Square : public Shape { public: virtual Square *clone() const { return new Square(*this); } } class Circle : public Shape { public: virtual Circle *clone() const { return new Circle(*this); } } class Octagon : public Shape { public: virtual Octagon *clone() const { return new Octagon(*this); } }
壞處:對每個子類別都要寫一個自己的 clone ,會出現大量長得很像卻又重複的程式碼。
General form of CRTP
// The Curiously Recurring Template Pattern (CRTP) template <class T> class Base { // methods within Base can use template to access members of Derived }; class Derived : public Base<Derived> { // ... };
What does it solve?
透過 CRTP 就對通用的函數就不用再寫一遍。
class Shape { public: virtual Shape* clone() const = 0; }; template <typename Derived> class CloneableShape : public Shape { public: virtual Derived* clone() const { return new Derived(static_cast<Derived const&>(*this)); } };
等於對 base class template 基於 自己(derived class) 「再 derive」出最終想要的,具有完整功能的 derived class 。這個就是 CRTP 。
class Square : public CloneableShape<Square> {};
Original link: eopXD