//Purpose: // Implement a compressed_enum class using: // // http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/mpl/if_recur.hpp // //Motivation: // The following post: // // http://article.gmane.org/gmane.comp.lib.boost.user/72228 // #include #include #include #include #include #include #include template < typename T > struct type_printer ; template < typename T > std::ostream& operator<< ( std::ostream& sout , type_printer const& ) { return type_printer::_(sout); } #define TYPE_PRINTER(TYPE) \ template\ <\ >\ struct type_printer\ < TYPE\ >\ {\ static\ std::ostream&\ _\ ( std::ostream&sout\ )\ {\ return sout<< #TYPE ;\ }\ }; using namespace boost::mpl; template < typename Enum //an enumeration. > struct enum_bits { static unsigned const size=0 //specializations should return //the actual size for given Enum. //This size is the number of bits //used to hold the value of an Enum. ; }; template < typename FwdSeq , typename Bits > struct state_down { typedef state_down type ; }; template < typename StateDown > struct fwd_not_empty : false_ { }; template < typename FwdHead , typename... FwdTail , typename Bits > struct fwd_not_empty < state_down < package , Bits > > : true_ { }; template < typename StateDown > struct sum_bits ; template < typename Tag , typename Enum , typename... FwdTail , unsigned Bits > struct sum_bits < state_down < package < pair< Tag, Enum> , FwdTail... > , integral_c > > { typedef state_down < package < FwdTail... > , integral_c::size> > type ; }; template < unsigned Bits > struct sum_bits < state_down < package < > , integral_c > > { typedef integral_c type ; }; template < typename StateDown , typename StateUp > struct inherit_get_put ; template < typename Tag , typename Enum , typename... FwdTail , typename Bits , typename StateUp > struct inherit_get_put < state_down < package< pair< Tag, Enum>, FwdTail...> , Bits > , StateUp > { struct type : StateUp { typedef StateUp super_t ; static unsigned const offset=super_t::offset-enum_bits::size ; using super_t:: get_ol //bring overloaded get_ol's from super types //in scope. ; using super_t:: put_ol //bring overloaded put_ol's from super types //in scope. ; Enum get_ol( Tag*)const { return this->template get_ol(); } void put_ol( Tag*, Enum e) { this->template put_ol(e); } }; }; template < typename StateDown > struct top_storage ; template < unsigned Bits > struct top_storage < state_down < package<> , integral_c > > /**@brief * Create storage. */ { struct type { static unsigned const size_bits=Bits ; static unsigned const offset=Bits ; template < typename Enum , unsigned Offset > Enum get_ol()const { unsigned const n=enum_bits::size; std::bitset eb; for( unsigned i=0; i()<<","<"; return e; } template < typename Enum , unsigned Offset > void put_ol( Enum e) { unsigned const n=enum_bits::size; std::bitset eb(e); for( unsigned i=0; i my_bits ; }; }; template < typename... Pairs > struct compressed_enums ; template < typename... Tags , typename... Enums > struct compressed_enums < pair... > : if_recur < state_down < package< pair< Tags, Enums>...> , integral_c< unsigned, 0> > , fwd_not_empty< arg< 1> > , sum_bits< arg<1> > , inherit_get_put< arg<1>, arg<2> > , top_storage< arg<1> > >::type { typedef compressed_enums < pair... > this_t ; typedef typename if_recur < state_down < package< pair< Tags, Enums>...> , integral_c< unsigned, 0> > , fwd_not_empty< arg< 1> > , sum_bits< arg<1> > , inherit_get_put< arg<1>, arg<2> > , top_storage< arg<1> > >::type super_t ; public: compressed_enums() { } template < typename Tag > struct get_result { typedef decltype((static_cast(0))->get_ol(static_cast(0))) type; }; template < typename Tag > typename get_result::type get()const { return this->super_t::get_ol((Tag*)0); } template < typename Tag , typename Enum > void put( Enum e) { this->super_t::put_ol((Tag*)0, e); } }; enum E1{e11,e12}; enum E2{e21,e22,e23}; enum E3{e31,e32,e33,e34}; struct T1; struct T2; struct T3; TYPE_PRINTER(T1) TYPE_PRINTER(T2) TYPE_PRINTER(T3) TYPE_PRINTER(E1) TYPE_PRINTER(E2) TYPE_PRINTER(E3) template<>struct enum_bits { static unsigned const size=2; }; template<>struct enum_bits { static unsigned const size=3; }; template<>struct enum_bits { static unsigned const size=4; }; typedef compressed_enums < pair , pair , pair > eos_t; int main() { std::cout<<":eos_t::size_bits="<="<()<<"\n"; std::cout<<"putting:\n"; eos_v.put(e12); eos_v.put(e23); eos_v.put(e34); std::cout<<":get="<()<<"\n"; std::cout<<":get="<()<<"\n"; std::cout<<":get="<()<<"\n"; return 0; }