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;
}
```

Reply via email to