Loki.StaticDispatcherをBoost.MPLで書ける

  • boost::python::type_infoはLoki::TypeInfoに相当する(ここでは使わない)


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

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

[]#include[][] <boost/mpl/reverse_fold.hpp>[]
[]#include[][] <boost/mpl/vector.hpp>[]
[]#include[][] <boost/mpl/sort.hpp>[]
[]#include[][] <boost/mpl/find.hpp>[]


[]#include[][] <boost/mpl/int.hpp>[]
[]#include[][] <boost/mpl/bool.hpp>[]
[]#include[][] <boost/mpl/and.hpp>[]
[]#include[][] <boost/type_traits.hpp>[]
[]#include[][] <iostream>[]

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

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

[]// static_dispatcher[]
[]// Executor : BinaryFunction[]
[]// Base[LR]hs : base type of (left|right) hand side[]
[]// Types[LR]hs : Sequence of (left|right) hand side[]
[]template[]< []class[] []Executor[],
[]bool[] []symmetric[],
[]class[] []BaseLhs[], []class[] []TypesLhs[],
[]class[] []BaseRhs[] = []BaseLhs[], []class[] []TypesRhs[] = []TypesLhs[],
[]class[] []ResultType[] = []void[] >
[]struct[] []static_dispatcher[]
{
[]typedef[] []typename[] []mpl[]::[]sort[]< []TypesLhs[], []bst[]::[]is_base_and_derived[]<[]_2[],[]_1[]> >::[]type[] []types_lhs[];
[]typedef[] []typename[] []mpl[]::[]sort[]< []TypesRhs[], []bst[]::[]is_base_and_derived[]<[]_2[],[]_1[]> >::[]type[] []types_rhs[];

[]// symmetric support[]
[]template[]< []class[] []SomeLhs[], []class[] []SomeRhs[] >
[]struct[] []call_traits[]
{
[]typedef[] []mpl[]::[]int_[]< []mpl[]::[]find[]<[]types_lhs[], []SomeLhs[]>::[]type[]::[]pos[]::[]value[] > []index_of_lhs[];
[]typedef[] []mpl[]::[]int_[]< []mpl[]::[]find[]<[]types_rhs[], []SomeRhs[]>::[]type[]::[]pos[]::[]value[] > []index_of_rhs[];

[]struct[] []normal_invocation[]
{
[]static[] []ResultType[] []do_dispatch[]([]SomeLhs[]& []lhs[], []SomeRhs[]& []rhs[], []Executor[] []exec[]) {
[]return[] []exec[]([]lhs[], []rhs[]);
}
};

[]struct[] []swap_invocation[]
{
[]static[] []ResultType[] []do_dispatch[]([]SomeLhs[]& []lhs[], []SomeRhs[]& []rhs[], []Executor[] []exec[]) {
[]return[] []exec[]([]rhs[], []lhs[]);
}
};

[]typedef[] []typename[] []mpl[]::[]if_[]<
[]mpl[]::[]and_[]< []mpl[]::[]bool_[]<[]symmetric[]>, []typename[] []mpl[]::[]less[]<[]index_of_rhs[], []index_of_lhs[]>::[]type[] >,
[]swap_invocation[], []normal_invocation[]
>::[]type[] []type[];
};

[]// dispatch_rhs[]
[]template[]< []class[] []SomeLhs[] >
[]struct[] []dispatch_rhs[]
{
[]struct[] []init_state_rhs_[]
{
[]static[] []ResultType[] []dispatch[]([]SomeLhs[]& []lhs[], []BaseRhs[]& []rhs[], []Executor[] []exec[]) {
[]return[] []exec[].[]on_error[]([]lhs[], []rhs[]);
}
};

[]template[]< []class[] []State[], []class[] []CheckingRhs[] >
[]struct[] []op_rhs_[]
{
[]static[] []ResultType[] []dispatch[]([]SomeLhs[]& []lhs[], []BaseRhs[]& []rhs[], []Executor[] []exec[]) {
[]if[] ([]CheckingRhs[]* []p2[] = []dynamic_cast[]<[]CheckingRhs[]*>(&[]rhs[])) {
[]wcout[] << []L[][]"rhs is found!..."[] << []typeid[]([]p2[]).[]name[]() << []endl[];
[]// return exec(lhs, *p2); // fire![]
[]return[] []call_traits[]<[]SomeLhs[], []CheckingRhs[]>::[]type[]::[]do_dispatch[]([]lhs[], *[]p2[], []exec[]); []// fire![]
}
[]else[] {
[]wcout[] << []L[][]"rhs is challenging next..."[] << []endl[];
[]return[] []State[]::[]dispatch[]([]lhs[], []rhs[], []exec[]);
}
}
};

[]typedef[] []typename[] []mpl[]::[]reverse_fold[]< []types_rhs[], []init_state_rhs_[], []op_rhs_[]<[]_1[],[]_2[]> >::[]type[] []type[];
};

[]// lhs folding[]
[]struct[] []init_state_lhs_[]
{
[]static[] []ResultType[] []dispatch[]([]BaseLhs[]& []lhs[], []BaseRhs[]& []rhs[], []Executor[] []exec[]) {
[]return[] []exec[].[]on_error[]([]lhs[], []rhs[]);
}
};

[]template[]< []class[] []State[], []class[] []CheckingLhs[] >
[]struct[] []op_lhs_[]
{
[]static[] []ResultType[] []dispatch[]([]BaseLhs[]& []lhs[], []BaseRhs[]& []rhs[], []Executor[] []exec[]) {
[]if[] ([]CheckingLhs[]* []p1[] = []dynamic_cast[]<[]CheckingLhs[]*>(&[]lhs[])) {
[]wcout[] << []L[][]"lhs is found!..."[] << []typeid[]([]p1[]).[]name[]() << []endl[];
[]return[] []dispatch_rhs[]<[]CheckingLhs[]>::[]type[]::[]dispatch[](*[]p1[], []rhs[], []exec[]);
}
[]else[] {
[]wcout[] << []"lhs is challenging next..."[] << []endl[];
[]return[] []State[]::[]dispatch[]([]lhs[], []rhs[], []exec[]);
}
}
};

[]typedef[] []typename[] []mpl[]::[]reverse_fold[]< []types_lhs[], []init_state_lhs_[], []op_lhs_[]<[]_1[], []_2[]> >::[]type[] []type[];

[]static[] []ResultType[] []go[]([]BaseLhs[]& []lhs[], []BaseRhs[]& []rhs[], []Executor[] []exec[]) {
[]return[] []type[]::[]dispatch[]([]lhs[], []rhs[], []exec[]);
}
};

[]// your application[]
[]struct[] []shape[] { []virtual[] ~[]shape[]() { } };
[]struct[] []rectangle[] : []shape[] { };
[]struct[] []ellipse[] : []shape[] { };
[]struct[] []poly[] : []shape[] { };
[]struct[] []unknown[] : []shape[] { };

[]struct[] []hatching_executor[]
{
[]void[] []operator[]()([]rectangle[]&, []rectangle[]&) { []wcout[] << []L[][]"rectangle*rectangle"[] << []endl[]; }
[]void[] []operator[]()([]rectangle[]&, []ellipse[]&) { []wcout[] << []L[][]"rectangle*ellipse"[] << []endl[]; }
[]void[] []operator[]()([]rectangle[]&, []poly[]&) { []wcout[] << []L[][]"rectangle*poly"[] << []endl[]; }
[]void[] []operator[]()([]ellipse[]&, []poly[]&) { []wcout[] << []L[][]"ellipse*poly"[] << []endl[]; }
[]void[] []operator[]()([]ellipse[]&, []ellipse[]&) { []wcout[] << []L[][]"ellipse*ellipse"[] << []endl[]; }
[]void[] []operator[]()([]poly[]&, []poly[]&) { []wcout[] << []L[][]"poly*poly"[] << []endl[]; }
[]void[] []on_error[]([]shape[]&, []shape[]&) { []wcout[] << []L[][]"error!"[] << []endl[]; }
};

[]typedef[] []mpl[]::[]vector[]<[]rectangle[], []ellipse[], []poly[]> []shapes[];
[]typedef[] []static_dispatcher[]<[]hatching_executor[], []true[], []shape[], []shapes[]> []dispatcher[];

[]void[] []test[]() {
[]shape[]* []p1[] = []new[] []ellipse[]();
[]shape[]* []p2[] = []new[] []poly[]();
[]hatching_executor[] []exec[];
[]dispatcher[]::[]go[](*[]p2[], *[]p1[], []exec[]);
}

}

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