Template Argumentの個数と順番を任意にする

  • boost::spirit::ruleで使われている
  • Named Template Argumentsのように名前を書かなくてもよい


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

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

[]#include[][] <iostream>[]
[]#include[][] <boost/mpl/vector.hpp>[]
[]#include[][] <boost/mpl/placeholders.hpp>[]
[]#include[][] <boost/type_traits.hpp>[]


[]#include[][] <boost/mpl/find_if.hpp>[]
[]#include[][] <boost/mpl/eval_if.hpp>[]
[]#include[][] <boost/mpl/identity.hpp>[]
[]#include[][] <boost/mpl/end.hpp>[]

[]// See: boost/spirit/core/non_terminal/impl/rule.ipp[]

[]namespace[] []pst_2005_03_14[] {
[]namespace[] []bst[] = ::[]boost[];
[]namespace[] []mpl[] = ::[]boost[]::[]mpl[];
[]using[] []mpl[]::[]_1[];

[]// tag bases[]
[]struct[] []door_base[] { };
[]struct[] []wall_base[] { };
[]struct[] []room_base[] { };

[]// helper[]
[]template[]< []typename[] []Base[], []typename[] []Default[],
[]typename[] []T0[], []typename[] []T1[], []typename[] []T2[] >
[]struct[] []get_param[] {
[]private[]:
[]typedef[] []mpl[]::[]vector[]<[]T0[],[]T1[],[]T2[]> []arguments[];
[]typedef[] []typename[] []mpl[]::[]find_if[]< []arguments[], []bst[]::[]is_base_and_derived[]<[]Base[], []_1[]> >::[]type[] []result_iter[];
[]public[]:
[]typedef[] []typename[] []mpl[]::[]eval_if[]<
[]bst[]::[]is_same[]<[]result_iter[], []typename[] []mpl[]::[]end[]<[]arguments[]>::[]type[]>,
[]mpl[]::[]identity[]<[]Default[]>, []mpl[]::[]deref[]<[]result_iter[]> >::[]type[] []type[];
};

[]// defaults[]
[]struct[] []default_door[] : []door_base[] { []/*...*/[] };
[]struct[] []default_wall[] : []wall_base[] { []/*...*/[] };
[]struct[] []default_room[] : []room_base[] { []/*...*/[] };

[]// MyHome[]
[]template[]< []typename[] []T0[] = []mpl[]::[]void_[], []typename[] []T1[] = []mpl[]::[]void_[], []typename[] []T2[] = []mpl[]::[]void_[] >
[]class[] []MyHome[] {
[]private[]:
[]typedef[] []typename[] []get_param[]<[]door_base[], []default_door[], []T0[], []T1[], []T2[]>::[]type[] []door_type[];
[]typedef[] []typename[] []get_param[]<[]wall_base[], []default_wall[], []T0[], []T1[], []T2[]>::[]type[] []wall_type[];
[]typedef[] []typename[] []get_param[]<[]room_base[], []default_room[], []T0[], []T1[], []T2[]>::[]type[] []room_type[];
[]public[]:
[]/*...*/[]
[]void[] []print[]() {
[]using[] []namespace[] []std[];
[]wcout[] << []L[][]"door_type is "[] << []typeid[]([]door_type[]).[]name[]() << []endl[];
[]wcout[] << []L[][]"wall_type is "[] << []typeid[]([]wall_type[]).[]name[]() << []endl[];
[]wcout[] << []L[][]"room_type is "[] << []typeid[]([]room_type[]).[]name[]() << []endl[] << []endl[];
}
};

[]struct[] []cheap_door[] : []door_base[] { []/*...*/[] };
[]struct[] []expensive_door[] : []door_base[] { []/*...*/[] };
[]struct[] []woody_wall[] : []wall_base[] { []/*...*/[] };
[]struct[] []stony_wall[] : []wall_base[] { []/*...*/[] };
[]struct[] []threeDK_room[] : []room_base[] { []/*...*/[] };
[]struct[] []twoDK_room[] : []room_base[] { []/*...*/[] };
[]struct[] []suites[] : []expensive_door[], []stony_wall[], []threeDK_room[] { []/*...*/[] };

[]void[] []test[]() {
[]MyHome[]<>().[]print[]();
[]MyHome[]<[]cheap_door[]>().[]print[]();
[]MyHome[]<[]twoDK_room[],[]expensive_door[]>().[]print[]();
[]MyHome[]<[]stony_wall[],[]twoDK_room[]>().[]print[]();
[]MyHome[]<[]threeDK_room[],[]expensive_door[],[]stony_wall[]>().[]print[]();
[]MyHome[]<[]suites[]>().[]print[]();
}
}

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