//Purpose: // use cross_product 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: // 1) For each field, F_i, form a pair, then form // a sequence of these pairs: // // ( pair // , pair // ... // , pair // ) // // 2) Then form the cross_product of these pairs: // // ( ( void, void, void, ... , void) // , ( F_1 , void, void, ... , void) // , ( void, F_2 , void, ... , void) // , ( F_1 , F_2 , void, ... , void) // // . // . // . // // , ( F_1 , F_2 , F_3 , ... , F_n ) // ) // // 3) Then use each element in the cross product as the ComponentSeq // argument to composite_tagged. // //ExternalSourceRequirements: // The variadic template mpl library: // https://svn.boost.org/trac/boost/browser/sandbox/variadic_templates // The variadic template fusion library: // https://svn.boost.org/trac/boost/browser/sandbox/SOC/2009/fusion // The composite_tagged_seq.zip from: // http://www.boostpro.com/vault/index.php?&directory=Data%20Structures // #include #include #include #include #include #include #include #include namespace boost { namespace client { enum field_enum { F_1=1 , F_2 , F_3 , F_4 , F_5 }; template < field_enum FieldType > struct field_type { typedef field_type type; }; template std::ostream& operator<< ( std::ostream& sout , field_type const& ) { sout<<"field_type="<::type , field_type::type , field_type::type , field_type::type , field_type::type > fields_t ; typedef void absent_tag ; typedef mpl::package absent_t ; typedef mpl::cross_product_pack < mpl::package >::type absent_fields_seq ; struct print_absent_fields { template < field_enum FieldType > void operator() ( mpl::package < absent_tag , field_type > ) { std::cout <<"package" <<"< absent_tag" <<", type="<\n"; } }; struct print_field { static int const width_absent=11; static int const width_field=2; void operator() ( mpl::aux::type_wrapper ) { if(first_field) { first_field = false; } else { std::cout<<", "; } std::cout< void operator() ( mpl::aux::type_wrapper< field_type > ) { if(first_field) { first_field = false; } else { std::cout<<", "; } std::cout<<"( type="; std::cout<::type select_fields_seq ; struct print_select_fields { template < typename... Fields > void operator() ( mpl::package ) { print_field field_printer; typedef mpl::package < mpl::aux::type_wrapper... > fields; std::cout<<"{ "; mpl::for_each(field_printer); std::cout<<"}\n"; } }; template < typename ComponentSeq > struct fields_subset : composite_tagged_seq < composite_tags::all_of_aligned , mpl::integral_c , ComponentSeq > { }; template < typename SelectFieldsSeq > struct fields_subsets ; template < typename... ComponentSeq > struct fields_subsets < mpl::package > { typedef mpl::package < fields_subset... > type ; }; void test(void) { print_absent_fields absent_fields_printer; std::cout<<"absent_fields_seq=\n"; mpl::for_each(absent_fields_printer); print_select_fields select_fields_printer; std::cout<<"size::value="<::value<<"\n"; std::cout<<"select_fields_seq=\n"; mpl::for_each(select_fields_printer); typedef fields_subsets::type fields_subsets_t; unsigned const size_subsets=mpl::size::value; unsigned const last_first_half=size_subsets/2-1; typedef mpl::at_c::type no_f1_t; no_f1_t no_f1_v; #if 0 // //The followings should get compile-time error about //not match for fields_subset::project(). // std::cout<<"no_f1_v.F_1="<()<<"\n"; #endif std::cout<<"no_f1_v.F_2="<()<<"\n"; std::cout<<"no_f1_v.F_3="<()<<"\n"; } }//exit client namespace }//exit boost namespace int main(void) { boost::client::test(); return 0; }