I've been using patterns such as this with no difficulty.
ctfe+mixins == it just works.
I don't know if there's some character limit where eventually the
ctfe string return will give up, but for moderate programs it
seems fine.
```d
// Copy fields from another struct, wrapping non-primary key
elements in Nullable!T
private static string UpdaterFields(STRUCT)() {
string[] s;
static foreach (idx, field; STRUCT.tupleof) {{
enum NAME = field.stringof;
enum bool isPrimary = hasUDA!(field, PRIMARY);
static if (isPrimary) {
enum typestr = format("typeof(STRUCT.%s)", NAME);
} else {
enum typestr = format("Nullable!(typeof(STRUCT.%s))",
NAME);
}
string[] udas;
static foreach (uda; __traits(getAttributes, field)) {
udas ~= "@("~uda.stringof~")";
}
auto udastr = udas.length ? udas.join(" ")~" " : "";
s ~= format("%s%s %s;", udastr, typestr, NAME);
}}
return s.join("\n");
}
pragma(msg, UpdaterFields!STRUCT);
mixin(UpdaterFields!STRUCT);
```