Thread overview
Struct field reordering
Jan 02, 2014
bearophile
Jan 02, 2014
Justin Whear
Jan 02, 2014
monarch_dodra
Jan 02, 2014
bearophile
Jan 02, 2014
monarch_dodra
January 02, 2014
Seen this on Reddit:

http://www.catb.org/esr/structure-packing/

It could be useful to have in Phobos some template that given pair-name pairs (or a struct type) returns those fields in a better packed order (without using align()).

See also:
https://d.puremagic.com/issues/show_bug.cgi?id=8873

Bye,
bearophile
January 02, 2014
On Thu, 02 Jan 2014 02:11:11 +0000, bearophile wrote:

> Seen this on Reddit:
> 
> http://www.catb.org/esr/structure-packing/
> 
> It could be useful to have in Phobos some template that given pair-name
> pairs (or a struct type) returns those fields in a better packed order
> (without using align()).
> 
> See also: https://d.puremagic.com/issues/show_bug.cgi?id=8873
> 
> Bye,
> bearophile

http://dlang.org/phobos/std_typecons.html#.alignForSize
January 02, 2014
On Thursday, 2 January 2014 at 02:11:13 UTC, bearophile wrote:
> Seen this on Reddit:
>
> http://www.catb.org/esr/structure-packing/
>
> It could be useful to have in Phobos some template that given pair-name pairs (or a struct type) returns those fields in a better packed order (without using align()).
>
> See also:
> https://d.puremagic.com/issues/show_bug.cgi?id=8873
>
> Bye,
> bearophile

Using "decreasing alignment size" then "decreasing size", I threw this together:

//--------
import std.stdio

//Actual useage
struct Test
{
    mixin PackedFields!(
        int, "a",
        char, "c1",
        int, "b",
        char, "c2",
        ushort, "c",
        char, "c3",
        ushort, "d",
        char[5], "arr",
    );
}

void main()
{
    //Proof of concept
    packedFields!(
        int, "a",
        char, "c1",
        int, "b",
        char, "c2",
        ushort, "c",
        char, "c3",
        ushort, "d",
        char[5], "arr",
    ).writeln();
    writeln(FieldTypeTuple!Test.stringof);
    writeln(Test.sizeof);
}

//Actual code:
import std.algorithm;
import std.traits;
import std.range;

struct Data
{
    uint aline;
    uint size;
    string type;
    string name;
}


Data[] packedFieldsImpl(Args...)()
{
    static if (Args.length)
    {
        auto ret = Data(Args[0].alignof, Args[0].sizeof, Args[0].stringof);
        static if (Args.length > 1 && is(typeof(Args[1]) == string))
        {
            ret.name = Args[1];
            return ret ~ packedFieldsImpl!(Args[2 .. $])();
        }
        else
            return ret ~ packedFieldsImpl!(Args[1 .. $])();
    }
    return Data[].init;
}

string packedFields(Args...)()
{
    auto data = packedFieldsImpl!Args();
    multiSort!(
        (a, b)=>a.aline > b.aline,
        (a, b)=>a.size  > b.size ,
    )(data);
    string ret;
    foreach(ref dat; data)
    {
        ret ~= dat.type ~ " " ~ dat.name ~ ";\n";
    }
    return ret;
}

mixin template PackedFields(Args...)
{
    mixin(packedFields!Args());
}
//--------

It produces:
//--------
int b;
int a;
ushort c;
ushort d;
char[5] arr;
char c2;
char c3;
char c1;
(int, int, ushort, ushort, char[5], char, char, char)
20
//--------

This technique uses basic ctfe + string mixin. It might be possible to avoid the ctfe altogether for pure meta? I'd have to compare the relative compiler cost.

The two questions I'm thinking are:
1) What is the cost of deploying this "large-scale".
2) Would it maybe be more convenient to have a "CheckPacked" template?

CheckPacked would have the same useage as PakedFields, but instead of re-ordering the fields, would simply validate them: This means lower cost on the compiler, and a better "what you see is what you get" layout. EG:

struct Test
{
    mixin PackedFields!(
        int, "a",
        char, "c1",
        int, "b", //HERE
        char, "c2",
        ushort, "c",
        char, "c3",
        ushort, "d",
        char[5], "arr",
    );
}

ERROR: field "b" of type int has higher alignment than field "c1" of type char. Please reorder.

struct Test
{
    mixin PackedFields!(
        int, "a",
        int, "b",
        ushort, "c",
        ushort, "d",
        char[5], "arr",
        char, "c1",
        char, "c2",
        char, "c3",
    );
}
//OK! Test is guaranteed optimally packed!
January 02, 2014
On Thursday, 2 January 2014 at 16:42:04 UTC, Justin Whear wrote:
> http://dlang.org/phobos/std_typecons.html#.alignForSize

Wow, that interface is horrible! It becomes a real mess if you have more than 3 members...

They should have used something like
http://dlang.org/phobos/std_bitmanip.html#.bitfields
January 02, 2014
Justin Whear:

> http://dlang.org/phobos/std_typecons.html#.alignForSize

Thank you, I have never seen that, nice :-) We should advertize more such D things on Reddit :-)

http://www.reddit.com/r/programming/comments/1u660a/the_lost_art_of_c_structure_packing/

Bye,
bearophile