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=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
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









"Nicholas Wilson" <iamthewilsonator hotmail.com> 