More C++ Idioms/奇妙に再帰したテンプレートパターン(Curiously Recurring Template Pattern)

意図

編集

派生クラス自身をテンプレート引数として、基本クラスを特殊化する。

別名

編集
  • CRTP
  • 上からの混入(Mixin-from-above)

動機

編集

型には依存しないが、型別にカスタマイズ可能な機能を基本クラスから抽出し、それらインタフェース、属性、動作を派生クラス用にカスタマイズしてから、派生クラスに混入(mix-in)させる。

解法とサンプルコード

編集

典型的には、基本クラステンプレートは、メンバ関数の本体(定義)はその宣言から非常に後になるまでインスタンス化されないという事実を活用する。そして、そのメンバ関数中で派生クラスのメンバ関数を、static_cast経由で利用する。例えば

  template <class Derived>
  struct base
  {
      void interface()
      {
          // ...
          static_cast<Derived*>(this)->implementation();
          // ...
      }
  
      static void static_interface()
      {
          // ...
          Derived::static_implementation();
          // ...
      }

      // デフォルトの実装は存在すれば、継承した派生クラスでオーバーライドされるかもしれないし、
      // 存在しない場合は、派生クラスでしなければならない(下記参照)
      void implementation();
      static void static_implementation();
  };

  // 奇妙に再帰したテンプレートパターン(Curiously Recurring Template Pattern (CRTP))
  struct derived_1 : base<derived_1>
  {
      // このクラスは base 版の implementation を用い、
      //void implementation();
      
      // …… static_implementation をオーバーライドする。
      static void static_implementation();
  };

  struct derived_2 : base<derived_2>
  {
      // このクラスは implementation をオーバーライドし、
      void implementation();

      // …… base 版の static_implementation を用いる。
      //static void static_implementation();
  };

関連するイディオム

編集

Barton-Nackman trick

編集

References

編集

Curiously Recurring Template Pattern on Wikipedia