digitalmars.D.learn - Packing enums
- qznc (16/16) Jun 29 2015 I stumbled upon this interesting programming challenge [0], which
- Nicholas Wilson (8/24) Jun 29 2015 Have you tried using bitfields?
- ketmar (40/48) Jul 01 2015 that's so easy that it's not even funny...
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
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=9800231Have 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
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