phobos
phobos copied to clipboard
Add Layout abstraction
This is much more useful and usable than Fields
or RepresentationTypeTuple
, which lose the essential information of offsets in data fields.
Thanks for your pull request, @andralex!
Bugzilla references
Your PR doesn't reference any Bugzilla issue.
If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.
Eh, we should relax the style checker a bit:
std/traits.d(2803:19)[error]: Expected `{` instead of `;`
std/traits.d(2803:19)[warn]: Empty declaration
std/traits.d(2804:24)[error]: Expected `{` instead of `;`
std/traits.d(2804:24)[warn]: Empty declaration
std/traits.d(8357:1)[error]: Expected `}` instead of `EOF`
std/traits.d(8357:1)[error]: Expected `}` instead of `EOF
in reference to:
// Intentionally undefined and undocumented.
struct __Vtable(C);
struct __Bookkeeping(C);
cc @wilzbach
The design and implementation look good and compact, but I'm uneasy about the static array expansion being more or less useless as it can generate enormous tuples.
This implementation will have rather bad compile-time performance.
Please count how many instances will be created for a Layout
with 4,8,32 fields.
sadly it does not seem to work @andralex please try:
{
struct S
{
uint u;
char[64] c64;
long l1, l2, l3, l4, l5, l6;
union {
S* s;
S*[32] s32;
}
}
pragma(msg, __traits(allMembers, Layout!S));
}
Ideas for tests missing:
-
align(1) struct S { byte a; int b; byte c; int d;}
-
align(2) struct S { byte a; int b; byte c; int d;}
-
struct S { byte a; align(1) int b; byte c; int d;}
- Test
Layout!(const S2)
. Specify that Layout discards all qualifiers on the types, also of struct members. Test withstruct S1 { int a; const S2 b}
(note the inner const) - Test with abstract class, class inheritance, interfaces.
- extern(C++) types
-
Layout!int
andLayout!(int[])
andLayout!(int[5])
(test errors or sane behavior) - Sorting for union of these structs:
align(1) struct S1 { byte a; int b; char c; char d; }; align(1) struct S2 { short a; short b; long c; byte d; }; align(1) struct S3 { int a; double b; };
(intentionally many different types, but avoiding pointers becausesize_t
is variable). - Perhaps important to take into account when testing that
size_t
can be 16bits.
This is great feedback you guys, thanks.
@JohanEngelen I figure it's a mistake to eliminate qualifiers (with Unqual
). Due to immutable
, immutable and mutable structures do not have compatible layout - e.g. you can't seat one on top of the other. Will change it such that qualifiers are preserved.
Also: currently the layout is sorted by offset first, order of declaration second. But the order of declaration is irrelevant. Better find a canonical order - will sort by offset first, type second. Are there better ways to sort types than by .stringof
?
All: how do I compare that two layouts are identical? is(Layout!A == Layout!B)
does not work because the instantiation of Layout
is not a type. What is the right way to compare that two instantiations of a template
are identical? Thx!
@andralex template instantiation is pure, so you can compare the template args for equality instead (recursively if necessary, as a template arg could be a template). Use std.traits.TemplateArgsOf
or some similar method.
I prefer to just use a struct
instead of a template
to avoid this problem altogether.
template instantiation is pure [...] @John-Colvin only if you are playing nice :p
@andralex I think we have a isSame
template.
which should do some sort of compare for you.
@UplinkCoder I assume you mean https://dlang.org/spec/traits.html#isSame
@andralex I'd like to see a usecase for this.
@andralex static if
/static assert
doesn't work?
Also: currently the layout is sorted by offset first, order of declaration second. But the order of declaration is irrelevant. Better find a canonical order - will sort by offset first, type second. Are there better ways to sort types than by .stringof?
Any advantages to secondary sorting with .sizeof
?
Also, suggestion to name DecomposedLayoutOf
(e.g.) - as it may make the reader more aware of purpose and how "Layout"ing is done (i.e. it decomposes the struct transitively)
Eh, we should relax the style checker a bit:
https://github.com/dlang/phobos/pull/6197
Why implement your own compile-time mergesort - what's wrong with std.meta.staticSort
?
Also, is there a great benefit to having the result be one long AliasSeq
instead of having a struct or template instance with Type
and offset
fields?
For comparison, here's how I would have implemented this (including names, since that's been requested):
https://gist.github.com/Biotronic/6182f24eabb444bca90f29d7a82bd428
This will be a powerful tool for the allocators, allowing us to create at compile time a smart mapping between types and allocators. For each group of objects with identical layouts, we can use the same allocator, allowing for safe memory reuse.