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