Inline aggregate types

Ethan Watson via Digitalmars-d digitalmars-d at puremagic.com
Thu Dec 1 12:31:32 PST 2016


https://github.com/Remedy-Entertainment/binderoo/blob/master/binderoo_client/d/src/binderoo/bitpacking.d

So I've been not-all-that-pleased with std.bitmanip.bitfields for 
a while. It's nice that it's there, but I'm binding to C++ 
objects where the meaningful default values require those packed 
values to have initial values. It's rather painful to get that 
working with the Phobos implementation.

I wanted to make a bitfield where you would simply give it a 
dummy struct type, complete with UDAs to tell it how many bits to 
take as well as standard default values. For example:

struct SomeBitField
{
   @PackSize( 3 ) int iSomeInt = 3;
   @PackSize( 1 ) bool bSomeBool = true;
   @PackSize( 4 ) int iSomeOtherInt;
}

I also don't want this struct to exist outside of the mixin 
declaration for it. Essentially, I want the code to boil down to:

mixin BitPack!( struct {
   @PackSize( 3 ) int iSomeInt = 3;
   @PackSize( 1 ) bool bSomeBool = true;
   @PackSize( 4 ) int iSomeOtherInt;
} );

Nice. Readable. Maintainable. You don't even need to read the 
documentation to add new members to the bit field, or change 
default values.

The compiler disagrees though. The second it sees that struct 
keyword, it freaks out. Sigh. Alrighty, what if we just remove 
the struct keyword? Nope. It tells me that I'm actually passing a 
lambda in to the BitPack mixin template.

Right. If that's the way you want to play compiler:

mixin template BitPack( Descriptor )
{
   mixin( GenerateBitPackBody!( Descriptor )() );
}

mixin template BitPack( string ElementDescription )
{
   mixin( "mixin BitPack!( typeof( { struct BitPackData { " ~ 
ElementDescription ~ " } return BitPackData.init; }() ) );" );
}

What in Zod's name is that abomination? Well. If it thinks it's a 
lambda that I'm trying to pass it, let's just make it explicit. 
I'll make an actual function literal. Take in the variables I 
want as a string instead of a plain old struct. Use a string 
mixin to generate this lambda. Get a typeof of the return type 
(deep in to Voldemort territory here) and passing that along to 
the main BitPack mixin template. And because I *really* don't 
want that struct to persist, my mixin template that takes the 
string descriptor inlines the entire thing with a string mixin.

So the invokation, while not as readable, looks like:

mixin BitPack!( "@PackSize( 3 ) int iSomeInt = 3; @PackSize( 1 ) 
bool bSomeBool = true; @PackSize( 4 ) int iSomeOtherInt;" );

I'm sure I just made someone cry looking at that.

I'm also sure there's plenty of other legit uses for inline 
aggregate types. So while the feature doesn't exist in the 
language yet, at least you can now see that there's quite a legit 
hacky-as-all-fuck workaround for it.


More information about the Digitalmars-d mailing list