#include #include #include #include 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 Derived , typename... Pairs > struct compressed_enums_impl ; template < typename Derived > struct compressed_enums_impl < Derived > { static unsigned const offset=0; protected: //only allow subclasses to access Derived::storage(). void const* get_ol()const { return static_cast(this)->storage(); } void* put_ol() { return static_cast(this)->storage(); } }; template < typename Derived , typename Tag , typename Enum , typename... Pairs > struct compressed_enums_impl < Derived , pair , Pairs... > : compressed_enums_impl < Derived , Pairs... > { typedef compressed_enums_impl < Derived , Pairs... > super_t; static unsigned const offset=enum_bits::size+super_t::offset; 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 { void const*pv=get_ol(); std::bitsetconst&pb=*static_castconst*>(pv); unsigned const size=enum_bits::size; std::bitset eb; for(unsigned i=0; i&pb=*static_cast*>(pv); unsigned const size=enum_bits::size; unsigned long l=e; std::bitset eb(l); for(unsigned i=0; i struct compressed_enums ; template < typename... Tags , typename... Enums > struct compressed_enums < pair... > : compressed_enums_impl < compressed_enums < pair... >//the CRTP pattern. , pair... > { typedef compressed_enums < pair... > this_t ; typedef compressed_enums_impl < this_t , pair... > super_t ; friend class compressed_enums_impl < this_t > //Allow top class to access the storage() member function. //That access is in protected section //of top class, which thus allows all //subclasses to access storage(). ; private: std::bitset my_bitset ; void const* storage()const { return static_cast(&my_bitset); } void* storage() { return static_cast(&my_bitset); } 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) { return 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; 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; 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 ;\ }\ }; TYPE_PRINTER(T1) TYPE_PRINTER(T2) TYPE_PRINTER(T3) TYPE_PRINTER(E1) TYPE_PRINTER(E2) TYPE_PRINTER(E3) template < typename Derived > struct type_printer < compressed_enums_impl < Derived > > { typedef compressed_enums_impl < Derived > this_t; static std::ostream& _ ( std::ostream&sout ) { sout<<"compressed_enums_impl\n< Derived\n>::offset="< struct type_printer < compressed_enums_impl < Derived , pair , Pairs... > > { typedef compressed_enums_impl < Derived , pair , Pairs... > this_t; static std::ostream& _ ( std::ostream&sout ) { sout<<"compressed_enums_impl" <<"\n< "<<"Derived" <<", pair< "<()<<", "<()<<"> \n" <<", " <() <::offset="< indent_outbuf(std::cout,2); std::cout<<":eos_t::offset="<="<()<<"\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"; std::cout<(); return 0; }