//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 Domains > struct cross_product_fold : fold < Domains , cross_prod_nil , cross_product, arg<2> > > { }; }//exit mpl namespace }//exit boost namespace #include #include #include #include #include #include #include #include #include //#define DEBUG_MPL #ifdef DEBUG_MPL #include #include #include #endif namespace fusion = boost::fusion; namespace boost { namespace mpl { template < int FieldId > struct field_name {}; template < int FieldId > struct field_type {}; typedef package < fusion::pair, field_type<1> > , fusion::pair, field_type<2> > , fusion::pair, field_type<1> > > fields_t ; struct absent_tag {}; typedef package absent_t ; typedef cross_product_fold < package >::type absent_fields_seq ; struct print_absent_fields { template < int FieldName , int FieldType > void operator() ( package < absent_tag , fusion::pair, field_type > > ) { std::cout <<"( name="< void operator() ( fusion::pair, field_type > ) { if(first_field) { first_field = false; } else { std::cout<<", "; } std::cout<<"( name="; std::cout<::type select_fields_seq ; struct print_select_fields { template < typename... Fields > void operator() ( package ) { print_field field_printer; typedef package fields; std::cout<<"{ "; for_each(field_printer); std::cout<<"}\n"; } }; template < typename AbsentOrField > struct is_absent : false_ {}; template < > struct is_absent < absent_tag > : true_ {}; template < typename AbsentOrFieldRow > struct rm_absent_row : remove_if < AbsentOrFieldRow , is_absent > , back_inserter > > { }; template < typename AbsentOrFieldTable > struct rm_absent_table : transform < AbsentOrFieldTable , rm_absent_row > , back_inserter > > { }; 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); typedef rm_absent_table::type rm_absent_seq; std::cout<<"rm_absent_seq=\n"; for_each(select_fields_printer); } }//exit mpl namespace }//exit boost namespace int main(void) { boost::mpl::test(); return 0; }