//Purpose: // use list_comprehension.cpp method to solve problem posted with headers: // /* From: "Hicham Mouline" Newsgroups: gmane.comp.lib.boost.user Subject: generate structs with all combinations of members from a given struct Date: Sat, 30 Jan 2010 13:37:52 +0700 */ //Method: // For each field, F_i, form a pair, then form // a sequence of these pairs: // // ( pair // , pair // ... // , pair // ) // // then form the cross_product of these pairs, then eliminate // any void elements in the cross_product elements. // //Requirements: // The variadic template mpl library: // https://svn.boost.org/trac/boost/browser/sandbox/variadic_templates // #include #include #include #include #include #include namespace boost { namespace mpl { template < typename Left , typename Right > struct cat_pkg ; template < typename... Left , typename... Right > struct cat_pkg < package , package > { typedef package < Left... , Right... > type ; }; template < typename One , typename Many > struct cross_one_many ; template < typename... Many > struct cross_one_many < package<> , package > { typedef package < Many... > type ; }; template < typename One , typename... Many > struct cross_one_many < One , package > { typedef package < typename push_back::type... > type ; }; template < typename Package , typename Op > struct transform_pkg ; template < typename... Args , typename Op > struct transform_pkg < package , Op > { typedef package < typename apply::type... > type ; }; template < typename Left , typename Right > struct cross_product { typedef typename transform_pkg < Left , cross_one_many < arg<1> , Right > >::type packages ; typedef typename fold < packages , package<> , cat_pkg,arg<2> > >::type type ; }; struct cross_prod_nil {}; template < typename... Right > struct cross_product < cross_prod_nil , package > { typedef package < package... > type ; }; template < typename LambdaExpr , typename Args > struct apply_each_pkg ; template < typename LambdaExpr , typename... Args > struct apply_each_pkg < LambdaExpr , package > { typedef package < typename apply < LambdaExpr , Args >::type ... > type ; }; template < typename LambdaExpr , typename Domains > struct list_comprehension /**@brief * The equivalent of haskell list comprehension expression * (see http://www.haskell.org/haskellwiki/List_comprehension ): * * [ LambdaExpr * | arg<1> <- at_c::type * , arg<2> <- at_c::type * ... * , arg <- at_c::type * ] * * where N=size::type::value * **@input_conditions: * LambdaExpr: * an mpl Lambda Expression with arity=N. * (http://www.boost.org/doc/libs/1_40_0/libs/mpl/doc/refmanual/lambda-expression.html) * Domains: * an mpl sequence of sequences, one for each argument to LambdaExpr. **@output_conditions: * Let: * Result = the list_comprehension:;type; * for all L in 0...N-1: * S_L = size >::type::value; * Then: * M = size::type::value = S_0*S_1*...*S_(N-1) * for each K in 0...M-1: * at_c::type = apply::type * where: * size::type::value = N; * for all L in 0...N-1: * at_c::type = some element in L-th domain of Domains. * Furthermore, each Args_K is "unique", i.e. it's complosed * different elements from at least one domain. */ { typedef typename fold < Domains , cross_prod_nil , cross_product, arg<2> > >::type arg_lists ; typedef unpack_args < LambdaExpr > unary_expr ; typedef typename apply_each_pkg < unary_expr , arg_lists >::type type ; }; }//exit mpl namespace }//exit boost namespace #include #include #include #include //#define DEBUG_MPL #ifdef DEBUG_MPL #include #include #include #endif namespace boost { namespace mpl { typedef package_c::pkg_type fields_t ; typedef package_c::pkg_type absent_t ; template < typename Arg1 , typename Arg2 > struct pkg_pair { typedef package type; }; typedef list_comprehension < pkg_pair,arg<2> > , package >::type absent_fields_seq ; struct print_absent_fields { template < int Absent , int Field > void operator() ( package < integral_c , integral_c > ) { std::cout<<"( Absent="< void operator() ( integral_c ) { if(first_field) { std::cout<<"{ "; first_field = false; } else { std::cout<<", "; } std::cout< struct selected_fields { typedef selected_fields type; }; typedef list_comprehension < selected_fields,arg<2>,arg<3> > , absent_fields_seq >::type select_fields_seq ; struct print_select_fields { //#define SIMPLE_PRINT #ifdef SIMPLE_PRINT template < typename F1 > void print ( F1 ) { std::cout<<"print_select_fields::print(F1)\n"; } #else template < typename F1 , typename F2 , typename F3 > void operator() ( selected_fields ) { print_field field_printer; typedef package fields; for_each(field_printer); std::cout<<"}\n"; } #endif }; void test(void) { print_absent_fields absent_fields_printer; std::cout<<"absent_fields_seq=\n"; for_each(absent_fields_printer); print_select_fields select_fields_printer; std::cout<<"size::value="<::value<<"\n"; std::cout<<"select_fields_seq=\n"; for_each(select_fields_printer); } }//exit mpl namespace }//exit boost namespace int main(void) { boost::mpl::test(); return 0; }