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.

Reply via email to