先日CRTP(Curiously Recursive Template Pattern)の勉強をしたので,それのメモ.
CRTPとは,基底クラスをクラステンプレートとして定義して,派生クラスでは,その基底クラスのテンプレート引数部分に自分自身を突っ込むものです.
基底クラス内で,派生クラスの型へキャストでき,派生クラスのみで定義した関数を呼び出せるのがポイント.
あとは,コード中に書いたコメント参照.
#include <iostream> template <typename Inherited> struct Base{ void apply(){ // Inheriedにダウンキャストし,そこで定義されているはずのapply_impl()を呼び出す static_cast<Inherited&>(*this).apply_impl(); } void test(){ std::cout << "Base" << std::endl; } }; struct Inherit1: public Base<Inherit1>{ void apply_impl(){ std::cout << "Inherit 1" << std::endl; } }; struct Inherit2: public Base<Inherit2>{ void apply_impl(){ std::cout << "Inherit 2" << std::endl; } }; // Baseの派生クラスのみを受け取る関数 template<typename T> void check(Base<T>& t){ // ポイント1:ここには,Base<T>のサブクラスのインスタンスしかこない(t.test()が呼べる) // ポイント2:Base<T>のサブクラスにapply_impl()が定義されてないとコンパイルエラー // ポイント3:tのapply()は多態的に呼び出される // ポイント4:仮想関数ではないため呼出しにオーバーヘッドがない t.apply(); t.test(); } int main(){ Inherit1 inh1; Inherit2 inh2; check(inh1); check(inh2); }
InheritedじゃなくてDerivedか?