Deriving a struct from another one via template: Easy way to propagate UDAs?
cc
cc at nevernet.com
Fri Mar 15 19:13:38 UTC 2024
On Thursday, 14 March 2024 at 23:19:37 UTC, Inkrementator wrote:
> I am trying to derive a struct from another. I want to modify
> each field such that type of it goes from some T to Nullable!T,
> preserving all fieldnames and UDAs.
This is trivially easy if your types are visible at module level,
and mixin is a fine tool for the job. It doesn't work quite so
well with [Voldemort
types](https://wiki.dlang.org/Voldemort_types).
```d
struct MyUDA { int q; }
struct Foo { int f; }
struct MyStruct {
@MyUDA(3) int x;
@MyUDA(4) Foo f;
@MyUDA(5) @MyUDA(7) string s;
}
auto generateUDAs(A...)() {
string[] udaStrs;
static foreach (uda; A)
udaStrs ~= "@(" ~ uda.stringof ~ ")";
return udaStrs;
}
struct Wrapped(S) {
static foreach (idx, field; S.tupleof) {
//pragma(msg, format(... can be used to preview
mixin(format("%s %s %s;", generateUDAs!(__traits(getAttributes,
field)).join(' '), Nullable!(typeof(field)).stringof,
field.stringof));
}
}
void main() {
MyStruct s;
s.x = 3;
s.f = Foo(1);
s.s = null;
Wrapped!MyStruct w;
w.x = s.x;
w.f = s.f;
w.s = s.s;
w.x.nullify;
w.f.nullify;
w.s.nullify; // strings/objects are already nullable though
static assert(__traits(getAttributes, w.s) ==
AliasSeq!(MyUDA(5), MyUDA(7)));
}
```
If you absolutely must though, you could do something like
```d
enum WrapMixin = q{
struct Wrapped(S) {
static foreach (field; S.tupleof)
mixin(format("%s %s %s;",
generateUDAs!(__traits(getAttributes, field)).join(' '),
Nullable!(typeof(field)).stringof, field.stringof));
}
};
void main() {
struct MyUDA { .....
struct MyStruct { .....
mixin(WrapMixin);
Wrapped!MyStruct w;
}
```
More information about the Digitalmars-d-learn
mailing list