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...