//Purpose: // Implement a compressed_enum class using: // // something analogous to apl decode and encode functions. // //Motivation: // The following post: // // http://article.gmane.org/gmane.comp.lib.boost.user/72290 // #include #include #include #include using namespace boost::mpl; template < typename Enum //an enumeration. > struct enum_size { static unsigned const size=0 //(The largest enumerator in Enum)+1. ; }; template < typename... Pairs > struct compressed_enums_impl ; template < > struct compressed_enums_impl < > /**@brief * Implements equation(5.7) of: * Timothy Budd * _An APL Compiler_ * Springer-Verlag(1988) * Where: * The args to get_ol and put_ol correspond to * equation(5.7) as follows: * * eq(5.7) here * ------- ---- * offset storage * e_i Stride * s_i enum_size::size */ { static unsigned const stride=1; protected: template < unsigned Stride , typename Enum , typename Storage > Enum get_ol( Storage const&storage)const { unsigned e=(storage/Stride)%enum_size::size; return Enum(e); } template < unsigned Stride , typename Enum , typename Storage > void put_ol( Enum e_out, Storage&storage) { Enum e_inp=get_ol(storage); //#define TRACE_PUT_OL #ifdef TRACE_PUT_OL std::cout<<"put_ol<"<::size<<">:\n"; std::cout<<"storage_inp="< struct compressed_enums_impl < pair , Pairs... > : compressed_enums_impl < Pairs... > { typedef compressed_enums_impl < Pairs... > super_t; static unsigned const stride=enum_size::size*super_t::stride; 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. ; template < typename Storage > Enum get_ol( Tag*, Storage const&storage)const { return this->get_ol< super_t::stride, Enum>( storage); } template < typename Storage > void put_ol( Tag*, Enum e, Storage&storage) { this->put_ol< super_t::stride>( e, storage); } }; template < typename Storage , typename... Pairs > struct compressed_enums ; template < typename Storage , typename... Tags , typename... Enums > struct compressed_enums < Storage , pair... > : compressed_enums_impl < pair... > { typedef compressed_enums_impl < pair... > super_t ; private: Storage my_storage ; public: compressed_enums() : my_storage(0)//all contained enums at min values. { } template < typename Tag > struct get_result { static super_t const& super_t_ref() ; static Tag* tag_ptr() ; static Storage const& storage_ref() ; void dummy()const { super_t const&super_v=super_t_ref(); Tag*tag_v=tag_ptr(); Storage const&storage_v=storage_ref(); auto e=super_v.get_ol( tag_v, storage_v); std::cout< typename get_result::type get()const { return this->super_t::get_ol( (Tag*)0, my_storage); } template < typename Tag , typename Enum > void put( Enum e) { return this->super_t::put_ol((Tag*)0, e, my_storage); } }; enum E1{e11,e12}; enum E2{e21,e22,e23}; enum E3{e31,e32,e33,e34}; struct T1; struct T2; struct T3; template<>struct enum_size { static unsigned const size=2; }; template<>struct enum_size { static unsigned const size=3; }; template<>struct enum_size { static unsigned const size=4; }; typedef compressed_enums < unsigned long , 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 < > struct type_printer < compressed_enums_impl < > > { typedef compressed_enums_impl < > this_t; static std::ostream& _ ( std::ostream&sout ) { sout<<"compressed_enums_impl\n<\n>::stride="< struct type_printer < compressed_enums_impl < pair , Pairs... > > { typedef compressed_enums_impl < pair , Pairs... > this_t; static std::ostream& _ ( std::ostream&sout ) { sout<<"compressed_enums_impl" <<"\n" <<"< pair< "<()<<", "<()<<"> \n" <<": " <() <::stride="< indent_outbuf(std::cout,2); std::cout<<":eos_t::stride="<(); eos_t eos_v; std::cout<<":get="<()<<"\n"; std::cout<<":get="<()<<"\n"; std::cout<<":get="<()<<"\n"; std::cout<<"putting:\n"; eos_v.put(e12);std::cout<<"put("<(e23);std::cout<<"put("<(e34);std::cout<<"put("<="<()<<"\n"; std::cout<<":get="<()<<"\n"; std::cout<<":get="<()<<"\n"; std::cout<<"putting:\n"; eos_v.put(e11);std::cout<<"put("<(e22);std::cout<<"put("<(e33);std::cout<<"put("<="<()<<"\n"; std::cout<<":get="<()<<"\n"; std::cout<<":get="<()<<"\n"; return 0; }