Loki::AbstractFactoryをBoost.MPLで書く


[]// abstract_factory.cpp : コンソール アプリケーションのエントリ ポイントを定義します。[]
[]//[]

[]#include[][] "stdafx.h"[]

[]#include[][] <boost/mpl/identity.hpp>[]
[]#include[][] <boost/mpl/inherit.hpp>[]
[]#include[][] <boost/mpl/inherit_linearly.hpp>[]
[]#include[][] <boost/mpl/bind.hpp>[]


[]#include[][] <boost/mpl/vector.hpp>[]
[]#include[][] <boost/mpl/quote.hpp>[]
[]#include[][] <boost/mpl/pop_front.hpp>[]
[]#include[][] <boost/mpl/front.hpp>[]
[]#include[][] <boost/mpl/lambda.hpp>[]

[]#include[][] <iostream>[]

[]// See: Modern C++ Design/Chapter9[]

[]namespace[] []pst_2005_03_17[] {
[]using[] []namespace[] []std[];
[]namespace[] []bst[] = []boost[];
[]namespace[] []mpl[] = []boost[]::[]mpl[];
[]using[] []mpl[]::[]_[]; []using[] []mpl[]::[]_1[]; []using[] []mpl[]::[]_2[];

[]template[]< []class[] []T[] >
[]struct[] []abstract_factory_unit_[]
{
[]virtual[] []T[]* []do_create[]([]mpl[]::[]identity[]<[]T[]>) = 0;
[]virtual[] ~[]abstract_factory_unit_[]() { }
};

[]// Note: mpl::quote creates MetafunctionClass from Metafunction[]
[]// looking better than "abstract_factory_unit_<_>"[]
[]typedef[] []mpl[]::[]quote1[]<[]abstract_factory_unit_[]> []abstract_factory_unit[];
[]// typedef abstract_factory_unit_<_> abstract_factory_unit; also OK[]

[]// abstract_factroy[]
[]// ProductList : ForwardSequence[]
[]// Unit : UnaryMetafunctionClass[]
[]template[]< []class[] []ProductList[], []class[] []Unit[] = []abstract_factory_unit[] >
[]struct[] []abstract_factory[]
: []mpl[]::[]inherit_linearly[]<
[]ProductList[],
[]// mpl::lambda makes LambdaExpression acceptable[]
[]mpl[]::[]inherit2[]< []_1[], []mpl[]::[]bind1[]<[]typename[] []mpl[]::[]lambda[]<[]Unit[]>::[]type[], []_2[]> >
>::[]type[]
{
[]typedef[] []ProductList[] []product_list[];
[]template[]< []class[] []T[] >
[]T[]* []create[]() {
[]// ambiguity buster[]
[]typedef[] []typename[] []mpl[]::[]apply[]<[]Unit[],[]T[]>::[]type[] []unit_type[];
[]unit_type[]& []unit_[](*[]this[]);
[]return[] []unit_[].[]do_create[]([]mpl[]::[]identity[]<[]T[]>());
}
};

[]template[]< []class[] []ConcreateProduct[], []class[] []Base[] >
[]struct[] []op_new_factory_unit_[] : []Base[]
{
[]// Note: You can't omit "type" typedef, because[]
[]// Base=abstract_factory=mpl::inherit2 returned from mpl::inherit_linerly,[]
[]// and mpl::inherit2 is a Metafunction returning itself![]
[]typedef[] []op_new_factory_unit_[] []type[];
[]private[]:
[]typedef[] []typename[] []Base[]::[]product_list[] []base_product_list[];
[]protected[]:
[]typedef[] []typename[] []mpl[]::[]pop_front[]<[]base_product_list[]>::[]type[] []product_list[];
[]public[]:
[]typedef[] []typename[] []mpl[]::[]front[]<[]base_product_list[]>::[]type[] []abstract_product[];
[]// override[]
[]virtual[] []abstract_product[]* []do_create[]([]mpl[]::[]identity[]<[]abstract_product[]>) {
[]return[] []new[] []ConcreateProduct[]();
}
};

[]typedef[] []mpl[]::[]quote2[]<[]op_new_factory_unit_[]> []op_new_factory_unit[];
[]// typedef op_new_factory_unit_<_,_> op_new_factory_unit; also possible[]

[]// concrete_factory[]
[]// OpNewFactoryUnit : BinaryMetafunctionClass[]
[]// ConcreteProductList : ForwardSequence[]
[]template[]<
[]class[] []AbstractFactory[],
[]class[] []OpNewFactoryUnit[] = []op_new_factory_unit[],
[]class[] []ConcreteProductList[] = []typename[] []AbstractFactory[]::[]product_list[]
>
[]struct[] []concreate_factory[]
: []mpl[]::[]inherit_linearly[]<
[]ConcreteProductList[],
[]mpl[]::[]bind2[]<[]typename[] []mpl[]::[]lambda[]<[]OpNewFactoryUnit[]>::[]type[],[]_2[],[]_1[]>,
[]AbstractFactory[] []// Root[]
>::[]type[]
{ };

[]// base enemies[]
[]struct[] []soldier[] { []virtual[] []void[] []kick[]() = 0; };
[]struct[] []monster[] { []virtual[] []void[] []scratch[]() = 0; };
[]struct[] []super_monster[] { []virtual[] []void[] []brast[]() = 0; };

[]// the abstract factory[]
[]typedef[] []mpl[]::[]vector[]<[]soldier[], []monster[], []super_monster[]> []base_enemy_list[];
[]typedef[] []abstract_factory[]<[]base_enemy_list[]> []abstract_enemy_factory[];

[]// easy level enemies[]
[]struct[] []silly_soldier[] : []soldier[] { []virtual[] []void[] []kick[]() { []wcout[] << []L[][]"silly kick"[] << []endl[]; } };
[]struct[] []silly_monster[] : []monster[] { []virtual[] []void[] []scratch[]() { []wcout[] << []L[][]"silly scratching"[] << []endl[]; } };
[]struct[] []silly_super_monster[] : []super_monster[] { []virtual[] []void[] []brast[]() { []wcout[] << []L[][]"silly brast"[] << []endl[]; } };

[]// easy level concrete factory []
[]typedef[] []mpl[]::[]vector[]<[]silly_soldier[], []silly_monster[], []silly_super_monster[]> []silly_enemy_list[];
[]typedef[] []concreate_factory[]<[]abstract_enemy_factory[], []op_new_factory_unit[], []silly_enemy_list[]> []easy_level_enemy_factory[];

[]// hard level enemies[]
[]struct[] []awesome_soldier[] : []soldier[] { []virtual[] []void[] []kick[]() { []wcout[] << []L[][]"awesome kick"[] << []endl[]; } };
[]struct[] []awesome_monster[] : []monster[] { []virtual[] []void[] []scratch[]() { []wcout[] << []L[][]"awesome scratching"[] << []endl[]; } };
[]struct[] []awesome_super_monster[] : []super_monster[] { []virtual[] []void[] []brast[]() { []wcout[] << []L[][]"awesome brast"[] << []endl[]; } };

[]// hard level concrete factory[]
[]typedef[] []mpl[]::[]vector[]<[]awesome_soldier[], []awesome_monster[], []awesome_super_monster[]> []awesome_enemy_list[];
[]typedef[] []concreate_factory[]<[]abstract_enemy_factory[], []op_new_factory_unit[], []awesome_enemy_list[]> []hard_level_enemy_factory[];

[]// test[]
[]void[] []test[]() {
[]bool[] []hard[] = []true[];

[]abstract_enemy_factory[]* []p_factory[];
[]if[] ([]hard[])
[]p_factory[] = []new[] []hard_level_enemy_factory[]();
[]else[]
[]p_factory[] = []new[] []easy_level_enemy_factory[]();
[]/* ... */[]

[]soldier[]* []p_mummy[] = []p_factory[]->[]create[]<[]soldier[]>();
[]p_mummy[]->[]kick[]();

[]monster[]* []p_orga[] = []p_factory[]->[]create[]<[]monster[]>();
[]p_orga[]->[]scratch[]();

[]/* ... */[]
}
} []// namespace pst_2005_03_17[]


[]int[] []_tmain[]([]int[] []argc[], []_TCHAR[]* []argv[][])
{
[]pst_2005_03_17[]::[]test[]();
[]wcin[].[]ignore[]();
[]return[] 0;
}