// NOTE: comes from std.bitmanip // PERMUTE_ARGS: private string myToString(ulong n) { return n < 10 ? "" ~ cast(char) (n + '0') : myToString(n / 10) ~ myToString(n % 10); } private string toStringSfx(ulong n) { return myToString(n) ~ (n > uint.max ? "UL" : "U"); } private string CreateAccessors( string store, T, string name, size_t len, size_t offset)() { static if (!name.length) { // No need to create any accessor return ""; } else { static const maskAllElse = ((1uL << len) - 1u) << offset, maskMyself = ~maskAllElse, signBitCheck = 1uL << (len - 1), extendSign = ~((1uL << len) - 1); string result; static if (is(T == bool)) { static assert(len == 1); // getter result ~= "bool " ~ name ~ "(){ return " ~ "("~store~" & "~toStringSfx(maskAllElse)~") != 0;}"; // setter result ~= "void " ~ name ~ "(bool v){" ~ "if (v) "~store~" |= "~toStringSfx(maskAllElse)~";" ~ "else "~store~" &= "~toStringSfx(maskMyself)~";}"; } else { // getter result ~= T.stringof ~ " " ~ name ~ "(){ auto result = " ~ "("~store~" & " ~ toStringSfx(maskAllElse) ~ ") >>" ~ toStringSfx(offset) ~ ";"; static if (T.min < 0) { result ~= "if (result >= " ~ toStringSfx(signBitCheck) ~ ") result |= " ~ toStringSfx(extendSign) ~ ";"; } result ~= " return cast(" ~ T.stringof ~ ") result;}"; // setter result ~= "void " ~ name ~ "(" ~ T.stringof ~ " v){ "~store~" = ("~store~" & " ~ toStringSfx(maskMyself) ~ ") | " ~ "((cast(typeof("~store~")) v << " ~ toStringSfx(offset) ~ ") & " ~ toStringSfx(maskAllElse) ~ ");}"; } return result; } } private string createStoreName(Ts...)() { static if (Ts.length == 0) return ""; else return Ts[1] ~ createStoreName!(Ts[3 .. $])(); } private string CreateFields(string store, size_t offset, Ts...)() { static if (!Ts.length) { static if (offset == ubyte.sizeof * 8) return "private ubyte " ~ store ~ ";"; else static if (offset == ushort.sizeof * 8) return "private ushort " ~ store ~ ";"; else static if (offset == uint.sizeof * 8) return "private uint " ~ store ~ ";"; else static if (offset == ulong.sizeof * 8) return "private ulong " ~ store ~ ";"; else static assert(false, ToString!(offset)); } else { return CreateAccessors!(store, Ts[0], Ts[1], Ts[2], offset)() ~ CreateFields!(store, offset + Ts[2], Ts[3 .. $])(); } } template BitFields(T...) { //pragma(msg, CreateFields!(createStoreName!(T)(), 0, T)()); mixin(CreateFields!(createStoreName!(T)(), 0, T)()); } struct FloatRep { mixin BitFields!( uint, "fraction", 23, uint, "exponent", 8, bool, "sign", 1); } struct DoubleRep { mixin BitFields!( ulong, "fraction", 52, uint, "exponent", 11, bool, "sign", 1); } struct Bug2355(string x) {} static assert(is(Bug2355!"a" U : Bug2355!V, string V)); int main() { return 0; }