|
Boost Users : |
Subject: Re: [Boost-users] Needs advices on design ( mpl or processor )
From: Allan Nielsen (a_at_[hidden])
Date: 2012-01-06 11:49:43
This is a much simple illustration of the problem I try to solve:
template<int OFFSET>
struct A {
enum O { offset = OFFSET };
enum S { size = 2 };
};
template<int OFFSET>
struct B {
enum O { offset = OFFSET };
enum S { size = 4 };
};
template < typename B0, typename B1, typename B2 >
struct C : public B0, B1, B2 {
};
int main(int argc, const char *argv[])
{
C< A<1>,
B< A<1>::offset * A<1>::size >,
A<
B< A<1>::offset * A<1>::size >::offset *
B< A<1>::offset * A<1>::size >::size
>
> c1;
// does the same
C< A<1>,
B< A<1>::size >,
A<
A<1>::size *
B< A<1>::size >::size
>
> c2;
return 0;
}
Is there a simpler way to let template arguments propagate through
derived classes?
On Fri, Jan 6, 2012 at 5:19 PM, Allan Nielsen <a_at_[hidden]> wrote:
> Hi
>
> This is not a specific questions directly related to Boost::mpl, but a request
> for help if somebody has the time...
>
> For the last couple of month I have been trying to learn to use the boost::mpl
> library.
>
> To learn to use the library I decided to use it for creating a
> "compressed-enum" library. The library should make it possible to store several
> enums in a single variable (for instance an unsigned int)
>
> Here is a simple example to give en idea:
>
> // example enums to play with
> struct TagA {
> Â Â enum Size { size = 4 };
> Â Â enum Max { max = Â 3 };
> Â Â enum E { A0 Â = Â 0, A1 Â = Â 1, A2 Â = Â 2, A3 Â = Â 3, };
> };
> struct TagB {
> Â Â enum Size { size = 4 };
> Â Â enum Max { max = Â 3 };
> Â Â enum E { B0 Â = Â 0, B1 Â = Â 1, B2 Â = Â 2, B3 Â = Â 3, };
> };
> struct TagC {
> Â Â enum Size { size = 4 };
> Â Â enum Max { max = Â 3 };
> Â Â enum E { C0 Â = Â 0, C1 Â = Â 1, C2 Â = Â 2, C3 Â = Â 3, };
> };
>
> struct First{};
> struct Second{};
>
> int main() {
> Â Â // using the compressed enums library
> Â Â typedef unsigned short STORAGE;
> Â Â typedef CompressedEnums< STORAGE,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â CompressedEnum<STORAGE, Â 1, TagA>,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â CompressedEnum<STORAGE, Â 4, TagB, First>,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â CompressedEnum<STORAGE, 16, TagB, Second>,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â CompressedEnumArray<STORAGE, 64, TagC, 5>
> Â Â Â Â Â Â Â Â Â Â Â Â Â > ENUMS;
>
> Â Â assert(sizeof(ENUMS) == 2));
> Â Â ENUMS enums;
> Â Â enums.set<TagA>(TagA::A2);
> Â Â enums.set<Second>(TagB::B2);
> Â Â enums.set<3, TagC>(TagC::C2);
>
> Â Â cout << enums.get<TagA>() << " " <<
> Â Â Â Â Â Â enums.get<Second>(TagB::B2) << " " <<
> Â Â Â Â Â Â enums.get<3, TagC>(TagC::C2) << endl;
> }
>
> CompressedEnums contains the storage variable, and inherit from all its
> template arguments, and make their methods available through tags.
> CompressedEnum and CompressedEnumArray only contains static methods which can
> find the enum in the storage variable.
>
> Here is a snippet of my implementation:
>
> template < typename STORAGE_TYPE,
> Â Â Â Â Â int OFFSET,
> Â Â Â Â Â typename ENUM_CONTAINER,
> Â Â Â Â Â typename TAG = typename ENUM_CONTAINER::E
> Â Â Â Â >
> struct CompressedEnum
> {
> Â Â typedef TAG ACCESS_TAG;
> Â Â typedef typename ENUM_CONTAINER::E INNER_TYPE;
>
> Â Â enum Offset { offset = OFFSET };
> Â Â enum Size { size = ENUM_CONTAINER::size };
>
> Â Â static INNER_TYPE get(const STORAGE_TYPE& data) {
> Â Â Â Â return (INNER_TYPE)((data / OFFSET) % size);
> Â Â }
>
> ----%<----%<----%<----%<----%<----%<----%<----%<--
> }
>
> template < typename STORAGE_TYPE,
> Â Â Â Â Â typename B00 = Dummy< 0>,
> Â Â Â Â Â typename B01 = Dummy< 1>,
> Â Â Â Â Â typename B02 = Dummy< 2>,
> Â Â Â Â Â typename B03 = Dummy< 3>
> Â Â Â Â >
> struct CompressedEnums : public B00, B01, B02, B03
> {
> Â Â typedef boost::mpl::map<boost::mpl::pair<typename B00::ACCESS_TAG, B00>,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â boost::mpl::pair<typename B01::ACCESS_TAG, B01>,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â boost::mpl::pair<typename B02::ACCESS_TAG, B02>,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â boost::mpl::pair<typename B03::ACCESS_TAG,
> B03> > TYPE_MAP;
>
> Â Â template<typename TAG>
> Â Â typename boost::mpl::at<TYPE_MAP, TAG>::type::INNER_TYPE
> Â Â get() const {
> Â Â Â Â return boost::mpl::at<TYPE_MAP, TAG>::type::get(data);
> Â Â }
>
> ----%<----%<----%<----%<----%<----%<----%<----%<--
> Â Â STORAGE_TYPE data;
> };
>
>
> The code works and does what it is suppose to (as far as I know) but I'm not
> very happy with the interface:
>
> typedef CompressedEnums< STORAGE,
>
> Â Â Â Â Â Â Â Â Â Â Â Â // 1 because it is the first
> Â Â Â Â Â Â Â Â Â Â Â Â CompressedEnum<STORAGE, Â 1, TagA>,
>
> Â Â Â Â Â Â Â Â Â Â Â Â // 4 because TagA::size == 4
> Â Â Â Â Â Â Â Â Â Â Â Â CompressedEnum<STORAGE, Â 4, TagB, First>,
>
> Â Â Â Â Â Â Â Â Â Â Â Â // 16 because TagA::size * TagB::size == 16
> Â Â Â Â Â Â Â Â Â Â Â Â CompressedEnum<STORAGE, 16, TagB, Second>,
>
> Â Â Â Â Â Â Â Â Â Â Â Â // 64 because TagA::size * TagB::size *
> TagB::size == 64
> Â Â Â Â Â Â Â Â Â Â Â Â CompressedEnumArray<STORAGE, 64, TagC, 5>
>
> Â Â Â Â Â Â Â Â Â Â Â > ENUMS;
>
> These magic numbers makes it very easy to make bugs when the code is
> restructured or changed, and it should be possible to calculate them
> automatic. If the magic numbers are replaced with their expresions the
> code will still break of the arguemnts are reordered.
>
> To accomplice this I have considered two solutions: macro or more templating...
>
> Using macroes I imagin the interface could look something like this:
>
> typedef CompressedEnums< STORAGE,
> Â Â Â Â Â Â Â Â Â Â Â Â ENUM_PACK( STORAGE, 1,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (CompressedEnum, TagA)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (CompressedEnum, TagB, First)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (CompressedEnum, TagB, Second)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (CompressedEnumArray, TagC, 5) ) > ENUMS;
> Which then would expand to the code manual entered above.
>
> Alternative using template I imagin that CompressedEnums could change
> CompressedEnum<STORAGE, 0, TagB, Second> ->
> CompressedEnum<STORAGE, 16, TagB, Second>
> automatic and then derive from that one automatic.
>
> I tried both, but non of my idea worked out very well, which is why I
> hope that one of you c++ experts could give me some hints.
>
>
> Best regards
> Allan W. Nielsen
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net