次のような型リストを作っておけば、
typedef boost::mpl::list<
BinOp,
IntLit,
FloatLit
> Types;
次のようなコードで型がリストの中で何番目かをコンパイル時定数で得ることが出来る。
boost::mpl::index_of<Types, IntLit>::type::value //== 1になる。
つまり、例えばIntLit::get_tagは次のように実装できることになる。
struct IntLit : Expr
{
//略
int get_tag() const { return boost::mpl::index_of<Types, IntLit>::type::value;} //Typesの中で何番目かを返す。
};
もちろんこんなのを派生クラス毎にいちいち書いていられない。
マクロを使って
struct IntLit : Expr
{
//略
GET_TAG_IMPL(IntLit);
};
のように書くようにする手もあるが、少し見苦しい。
struct IntLit : DerivedImpl<IntLit, Expr>
{
//略
};
くらいにしたいところなので、
template<typename Derived, typename Base>
struct DerivedImpl : Base
{
// コンストラクタ
DerivedImpl() : Base(){}
template<typename A0> DerivedImpl(const A0 &a0) : Base(a0){}
template<typename A0, typename A1> DerivedImpl(const A0 &a0, const A1 &a1) : Base(a0, a1){}
// get_tagの実装
int get_tag() const { return boost::mpl::index_of<typename Base::DerivedTypes::Types, Derived>::type::value;}
};
のようなget_tagを実装してくれるクラスを用意することにした。
これが動くには基底クラスにDerivedTypes::Typesという名前で派生クラスの型リストが無ければならない。
struct Expr
{
struct DerivedTypes;
//略
};
//各派生クラスの定義。
struct Expr::DerivedTypes
{
typedef boost::mpl::list<
BinOp,
IntLit,
FloatLit
> Types;
};
Exprに直接型リストを書かないのは、前方宣言をできるだけしないでいいようにするためである。