#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... Pairs > struct enums_offsets_impl ; template < typename Derived > struct enums_offsets_impl < Derived > { static unsigned const offset=0; protected://only allow subclasses to access get_ol. unsigned char const* get_ol()const { return static_cast(*this).buffer(); } unsigned char* put_ol() { return static_cast(*this).buffer(); } }; template < typename Derived , typename Tag , typename Enum , typename... Pairs > struct enums_offsets_impl < Derived , pair , Pairs... > : enums_offsets_impl < Derived , Pairs... > { typedef enums_offsets_impl < Derived , Pairs... > super_t; static unsigned const offset=enum_bits::size+super_t::offset; using super_t:: get_ol //bring overloaded get_ol(Tag)'s from super types //in scope. ; using super_t:: put_ol //bring overloaded get_ol(Tag)'s from super types //in scope. ; Enum get_ol(Tag*)const { unsigned const beg_bit=super_t::offset%CHAR_BIT; unsigned char const*pc=get_ol(); void const*pv=static_cast(pc); std::bitsetconst*pb=static_castconst*>(pv); unsigned const size=enum_bits::size; std::bitset eb; for(unsigned i=0; i(pc); std::bitset*pb=static_cast*>(pv); unsigned const size=enum_bits::size; unsigned long l=e; std::bitset eb(l); for(unsigned i=0; i struct enums_offsets ; template < typename... Tags , typename... Enums > struct enums_offsets < pair... > : enums_offsets_impl < enums_offsets < pair... >//the CRTP pattern. , pair... > { typedef enums_offsets < pair... > this_t ; typedef enums_offsets_impl < this_t , pair... > super_t ; friend class enums_offsets_impl < this_t > //Allow top class to access the buffer() member function. //That access is in protected section //of top class, which thus allows all //subclasses to access buffer(). ; private: unsigned char my_buffer [ super_t::offset/CHAR_BIT ] ; unsigned char const* buffer()const { return my_buffer; } unsigned char* buffer() { return my_buffer; } public: enums_offsets() { for(unsigned i=0; i 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 enums_offsets < pair , pair , pair > eos_t; #include int main() { std::cout<<":eos_t::offset="<="<()<<"\n"; std::cout<<"putting:\n"; eos_v.put(e11); eos_v.put(e22); eos_v.put(e33); std::cout<<":get="<()<<"\n"; std::cout<<":get="<()<<"\n"; std::cout<<":get="<()<<"\n"; return 0; }