On Monday, 22 May 2017 at 21:03:42 UTC, Bastiaan Veelo wrote:
`
void main()
{
        import std.stdio;
        struct S
        {
                int i;
                union
                {
                        int a;
                        double b;
                }
        }
        S s;
        writeln(s);                  // S(10, #{overlap a, b})
        import std.traits;
        writeln([FieldNameTuple!S]); // ["i", "a", "b"]
}
`

Is there a way to detect at CT that S has overlapping data members, when an anonimous union is used as above?

Thanks,
Bastiaan.

There isn't a built-in one. The best I can muster at 1AM is finding all fields that have the same offset:

size_t[] memberOffsetsOf(T)()
{
    size_t[] result;
    foreach(i, _; typeof(T.tupleof))
        result ~= T.tupleof[i].offsetof;
    return result;
}

string[] overlappingFieldsOf(T)()
{
    import std.traits : FieldNameTuple;
    import std.range : array, enumerate;
    import std.algorithm : map, filter, count;
    enum offsets = memberOffsetsOf!T;
    auto names = [FieldNameTuple!T];
    bool isOverlapping(size_t i) {
        return offsets.count(offsets[i]) > 1;
    }
    return names
           .enumerate
           .filter!(a => isOverlapping(a.index))
           .map!(a => a.value)
           .array;
}

void main()
{
        import std.stdio;
        struct S
        {
                int i;
                union
                {
                        int a;
            double b;
                }
        int j;
        union
        {
            struct { short n, m; }
            float k;
        }
        }
        S s;

    writeln(overlappingFieldsOf!S); // ["a", "b", "n", "k"]
}

which is not quite the same as full overlap. This looks like a fun exercise, considering fields can also have arbitrary alignment...

Reply via email to