#ifndef COMMON_STRUCT_MEMBERS_COMBOS_HPP #define COMMON_STRUCT_MEMBERS_COMBOS_HPP #include ///////////////////////////////////////////////////////////////////// /// Generates 1 struct and its definition for each possible /// combination of members of a primary struct ///////////////////////////////////////////////////////////////////// #define STRUCT_MEMBERS_COMBOS(struct_name,struct_members) \ BOOST_PP_SEQ_FOR_EACH(\ MAKE_STRUCT,\ struct_name,\ SUBSETS2(\ BOOST_PP_SEQ_SIZE(struct_members),\ BOOST_PP_SEQ_TO_TUPLE(struct_members)\ )\ ) /// /// Generates a PP sequence of just the struct names, not defintions /// see above /// #define STRUCT_MEMBERS_COMBOS_NAMES(struct_name,struct_members) \ BOOST_PP_SEQ_FOR_EACH(\ MAKE_STRUCT_NAME,\ struct_name,\ SUBSETS2(\ BOOST_PP_SEQ_SIZE(struct_members),\ BOOST_PP_SEQ_TO_TUPLE(struct_members)\ )\ ) #define SUBSETS2(size, values) BOOST_PP_CAT(SUBSETS_, size) values /// /// Hardcoded recursion algo for performance /// If the primary struct has more than 8 members, more macros are required /// #define SUBSETS_1(a1) ((a1)) #define SUBSETS_2(a1,a2) SUBSETS_COMBINE(a2, SUBSETS_1(a1)) #define SUBSETS_3(a1,a2,a3) SUBSETS_COMBINE(a3, SUBSETS_2(a1,a2)) #define SUBSETS_4(a1,a2,a3,a4) SUBSETS_COMBINE(a4, SUBSETS_3(a1,a2,a3)) #define SUBSETS_5(a1,a2,a3,a4,a5) SUBSETS_COMBINE(a5, SUBSETS_4(a1,a2,a3,a4)) #define SUBSETS_6(a1,a2,a3,a4,a5,a6) SUBSETS_COMBINE(a6, SUBSETS_5(a1,a2,a3,a4,a5)) #define SUBSETS_7(a1,a2,a3,a4,a5,a6,a7) SUBSETS_COMBINE(a7, SUBSETS_6(a1,a2,a3,a4,a5,a6)) #define SUBSETS_8(a1,a2,a3,a4,a5,a6,a7,a8) SUBSETS_COMBINE(a8, SUBSETS_7(a1,a2,a3,a4,a5,a6,a7)) #define SUBSETS_COMBINE(x, seq_seq) \ seq_seq \ ((x)) \ BOOST_PP_SEQ_FOR_EACH(SUBSETS_COMBINE_IMPL, x, seq_seq) #define SUBSETS_COMBINE_IMPL(r, elem, seq) (seq (elem)) #define STATEMENT_FROM_PAIR(pair) BOOST_PP_TUPLE_ELEM(2,0,pair) BOOST_PP_TUPLE_ELEM(2,1,pair); /// /// Generate for this combination, the struct defintion including the operator= /// e.g. /// struct S_member4_member7 { /// /// type4 member4; /// type7 member7; /// }; #define MAKE_STRUCT(r,data,elem) \ (struct BOOST_PP_TUPLE_ELEM(2,1,BOOST_PP_WHILE(WHILE_PRED, WHILE_OP,(elem,data))) \ { \ BOOST_PP_TUPLE_ELEM(2,1,BOOST_PP_WHILE(WHILE_PRED, WHILE_OP,(elem,data)))(const data & rhs) \ BOOST_PP_FOR(elem, FOR_PRED, FOR_OP, FOR_MACRO) };) #define FOR_PRED(r,state) BOOST_PP_SEQ_SIZE(state) #define FOR_OP(r,state) BOOST_PP_SEQ_POP_FRONT(state) #define FOR_MACRO(r,state) STATEMENT_FROM_PAIR(BOOST_PP_SEQ_HEAD(state)) #define WHILE_PRED(r,state) BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(2,0,state)) #define WHILE_OP(r,state) \ (\ BOOST_PP_SEQ_POP_FRONT(BOOST_PP_TUPLE_ELEM(2,0,state)),\ BOOST_PP_CAT(\ BOOST_PP_TUPLE_ELEM(2,1,state),\ BOOST_PP_CAT(\ _,\ BOOST_PP_TUPLE_ELEM(2,1,BOOST_PP_SEQ_HEAD(BOOST_PP_TUPLE_ELEM(2,0,state)))\ )\ )\ ) /// /// Generate for this combination, the struct name /// e.g. (S_member4_member7) #define MAKE_STRUCT_NAME(r,data,elem) (BOOST_PP_TUPLE_ELEM(2,1,BOOST_PP_WHILE(WHILE_PRED, WHILE_OP,(elem,data)))) #endif // COMMON_STRUCT_MEMBERS_COMBOS_HPP