www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Packing enums

reply "qznc" <qznc web.de> writes:
I stumbled upon this interesting programming challenge [0], which 
imho should be possible to implement in D. Maybe someone here 
wants to try.

Task: Given two enums with less than 256 states, pack them into 
one byte and provide convenient accessor functions.

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;

Of course, you can generalize to "n enums packed into a minimal 
number of bytes".


[0] https://news.ycombinator.com/item?id=9800231
Jun 29 2015
next sibling parent "Nicholas Wilson" <iamthewilsonator hotmail.com> writes:
On Monday, 29 June 2015 at 22:05:47 UTC, qznc wrote:
 I stumbled upon this interesting programming challenge [0], 
 which imho should be possible to implement in D. Maybe someone 
 here wants to try.

 Task: Given two enums with less than 256 states, pack them into 
 one byte and provide convenient accessor functions.

 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;

 Of course, you can generalize to "n enums packed into a minimal 
 number of bytes".


 [0] https://news.ycombinator.com/item?id=9800231
Have you tried using bitfields? enum X : byte { A, B, C }; enum Y : byte { foo, bar, baz }; mixin(bitfields!( X, "x", 3, Y, "y", 3, uint, "", 2));
Jun 29 2015
prev sibling parent "ketmar" <ketmar ketmar.no-ip.org> writes:
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 }
Jul 01 2015