CRTPの勉強

先日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);
}