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> {};

如果你覺得有收穫,可以用 30 NTD 來支持我繼續創作更多內容。因為做自己喜歡的事而得到報酬,是再好不過的事了。(街口支付)

Author: eopXD

Hi 我是 eop ,希望人生過得有趣有挑戰XD

Leave a Reply