混入スタイルの基底クラス

この前Effective C++を読み返していると、テンプレート引数をクラス定義で使っていないのに、
テンプレートクラスになっている物があったので、いろいろ考えた結果、
派生クラス作成時に派生クラス名をテンプレート引数として渡すことによって、
基底クラスを別のものにするために使ってるんじゃないかという結論に


ということで、とりあえず一度サンプルを書いてためしてみた

#include <iostream>
#include <vector>

struct Base
{
	static int baseCount;
	Base(){baseCount++;}
	Base(const Base& rhs){baseCount++;}
	~Base(){baseCount--;}
};

template<class T>
struct TemplateBase
{
	static int templateBaseCount;
	TemplateBase(){templateBaseCount++;}
	TemplateBase(const TemplateBase& rhs){templateBaseCount++;}
	~TemplateBase(){templateBaseCount--;}
};

struct Derived1 : public TemplateBase<Derived1> , public Base
{
	static int der1Count;
	Derived1(){der1Count++;}
	Derived1(const Derived1& rhs){der1Count++;}
	~Derived1(){der1Count--;}
};

struct Derived2 : public TemplateBase<Derived2> , public Base
{
	static int der2Count;
	Derived2(){der2Count++;}
	Derived2(const Derived2& rhs){der2Count++;}
	~Derived2(){der2Count--;}
};

int TemplateBase<Derived1>::templateBaseCount = 0;
int TemplateBase<Derived2>::templateBaseCount = 0;
int Base::baseCount = 0;
int Derived1::der1Count = 0;
int Derived2::der2Count = 0;

int main()
{
	std::vector<Derived1> der1Vec(10);
	std::vector<Derived2> der2Vec(20);

	std::cout << "BaseCount:" << Base::baseCount << std::endl;
	std::cout << "templateBase<Derived1>Count:" << TemplateBase<Derived1>::templateBaseCount << std::endl;
	std::cout << "templateBase<Derived2>Count:" << TemplateBase<Derived2>::templateBaseCount << std::endl;
	std::cout << "Der1Count:" << Derived1::der1Count << std::endl;
	std::cout << "der2Count:" << Derived2::der2Count << std::endl;
}

実行結果:
BaseCount:30
templateBaseCount:10
templateBaseCount:20
Der1Count:10
der2Count:20
結果を見ると、確かにstaticメンバーが共有されていないので、別の基底クラスから継承したのと同じような効果になっているのがわかる。


まあ

int TemplateBase<Derived1>::templateBaseCount = 0;
int TemplateBase<Derived2>::templateBaseCount = 0;
int Base::baseCount = 0;
int Derived1::der1Count = 0;
int Derived2::der2Count = 0;

で、テンプレート引数毎に初期化しなければいけない時点で大体わかってたことなんだけど。


その後、調べてみると、こういった手法を混入スタイルとか呼ぶらしい
今回の例だと単純に基底クラスを分離するためだけに使っているけれど
こういったかんじの派生クラス名を基底クラスのテンプレートパラメーターにする手法は
他にもいろいろ使い道があるようなので、ちょっと調べてみることとしよう。