テンプレートから派生するクラスに関するメモ

たとえば頂点をI個持つ抽象的なクラスBase をテンプレートにして、辺や三角形の面といったクラスを派生させるとする。

geo.cc
----
template <typename T, int I>
class Base
{
    public:
     int flag;
     int vtx[I];
     static BinaryTree *bt;//よそで定義された二分木探索クラス

     Base<T,I>(int *v)
     {
	 flag=0;
	 int i;
	 for(i=0;i<I;i++) vtx[i]=v[i];
	 bt->Insert(v);//二分木に登録
     };

     ~Base<T,I>(){ bt->Delete(vtx); };//二分木から削除

     static T *Find(int *vtxlist)
     {
	 T *result= (T *)bt->Find(vtxlist); //二分木探索
         return result;
     }
};

class Edge: public Base<Edge, 2>
{
    public:
    Edge(int *v):Base<Edge, 2>(v){};
    class Tri *pTri[2];
};
BinaryTree *Edge::bt = new BinaryTree(2);

class Tri: public Base<Tri, 3>
{
    public:
    Edge *pEdge[3];

    Tri(int *v):Base<Tri, 3>(v)
    {
	int e;
	//Edge 登録
	for(e=0;e<3;e++)
	{
	    int vtmp[2];
	    vtmp[0]=vtx[e];
	    vtmp[1]=vtx[(e+1)%3];
	    Edge *e = Edge::Find(vtmp);
	    pEdge[i]= e;

	    if(e->pTri[0]==NULL)
		e->pTri[0]=this;
	    else
		e->pTri[1]=this;
	}
    }
}
BinaryTree *Tri::bt = new BinaryTree(3);

c++ -c geo.cc としたとき、Edge::Findは生成されるが Tri::Find はコードが生成されない。このファイルの中で呼び出してないから。対応としては、Base クラスにメソッドを全部呼ぶメソッド dummy()を一つ作り、このファイルの中で

static void dummyAll()
{
    Edge::dummy();
    Tri::dummy();
}

などとすればとりあえずOK。dummyAllは実際には呼ばなくてもいい。