Thread overview | |||||
---|---|---|---|---|---|
|
June 29, 2015 Packing enums | ||||
---|---|---|---|---|
| ||||
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 |
June 30, 2015 Re: Packing enums | ||||
---|---|---|---|---|
| ||||
Posted in reply to qznc | 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));
|
July 01, 2015 Re: Packing enums | ||||
---|---|---|---|---|
| ||||
Posted in reply to qznc | 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 } |
Copyright © 1999-2021 by the D Language Foundation