Packing enums

ketmar via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Jul 1 00:45:08 PDT 2015


On Monday, 29 June 2015 at 22:05:47 UTC, qznc wrote:

> Something like this:
>
> enum X { A, B, C };
> enum Y { foo, bar, baz };
> alias both = TwoEnums!(X,Y);
> static assert(both.sizeof == 1);
> both z;
> z.X = B;
> z.Y = bar;

that's so easy that it's not even funny...

enum X { A, B, C };
enum Y { foo, bar, baz };


align(1) struct TwoEnums(E0, E1) if (is(E0 == enum) && is(E1 == 
enum)) {
   private import std.string : format;
   static assert(E0.min >= 0 && E1.min >= 0 && E0.max < 256 && 
E1.max < 256 && E0.max+E1.max < 256, "enums can't be packed");
   static assert(E0.max > 0 && E1.max > 0, "can't pack dummy 
enums");
align(1):
   ubyte v_;
   template opDispatch(string mt) {
     static if (mt == E0.stringof) {
       @property E0 implE0 () { return cast(E0)(v_%E0.max); }
       @property void implE0 (E0 nv) { v_ = 
cast(ubyte)((v_/E0.max)*E0.max+cast(ubyte)nv); }
       alias opDispatch = implE0;
     } else static if (mt == E1.stringof) {
       @property E1 implE1 () { return cast(E1)(v_/E0.max); }
       @property void implE1 (E1 nv) { v_ = 
cast(ubyte)((v_%E0.max)+cast(ubyte)nv*E0.max); }
       alias opDispatch = implE1;
     } else {
       static assert(0);
     }
   }
}

alias both = TwoEnums!(X, Y);
static assert(both.sizeof == 1);

void main () {
   import std.stdio;
   both z;
   writeln(z.X, " ; ", z.Y, "; v_=", z.v_); // A ; foo; v_=0

   z.X = X.B;
   writeln(z.X, " ; ", z.Y, "; v_=", z.v_); // B ; foo; v_=1

   z.Y = Y.bar;
   writeln(z.X, " ; ", z.Y, "; v_=", z.v_); // B ; bar; v_=3
}


More information about the Digitalmars-d-learn mailing list