I would like to simplify a situation when i need to change values of some fields of my struct but keep other fields unchanged. Standard situation looks like this.
struct MyStruct {
int field1;
double field2;
string field3;
int field4;
string field5;
}
MyStruct myStruct = //...
// i need to change some values
myStruct.field1 = 10;
myStruct.field2 = 0.5;
myStruct.field5 = "hello";
// and it gets even uglier if struct is inside some complex structure i.e.:
myArray[0].someOtherStruct.myStruct.field1 = 10;
myArray[0].someOtherStruct.myStruct.field2 = 0.5;
myArray[0].someOtherStruct.myStruct.field5 = "hello";
I propose two solutions:
-
- automatically generate setter for every field which returns reference to the struct
-
- automatically generate an assign function with all fields as optional params, but assign only those which are given by user (no idea how to implement this)
My attempt to implement solution 1.
myStruct
.setfield1(10)
.setfield2(0.5)
.setfield5("hello");
// or just make it in one line
myStruct.setfield1(10).setfield2(0.5).setfield5("hello");
I tried to implement it with mixin template:
mixin template GenerateSetters(T) {
enum fieldNames = FieldNameTuple!T;
alias fieldTypes = FieldTypeTuple!T;
enum typeName = fullyQualifiedName!T;
string generateFunctions() {
string param;
string fuctions;
foreach (i, fieldName; fieldNames) {
param = fieldTypes[i].stringof ~ " " ~ fieldName;
fuctions ~="ref "~typeName~" set"~fieldName~"(return ref "~typeName~" a, "
~ param ~ ") {\n"~
" a."~fieldName~" = "~fieldName~";\n"~
" return a;\n"~
"}\n";
}
return fuctions;
}
//pragma(msg, generateFunction());
mixin(generateFunctions());
}
struct MyStructTest {
int field1;
double field2;
string field3;
string field4;
string field5;
}
mixin GenerateSetters!(MyStructTest); // you need to call this after struct definition
It works, but if it was built into the language it could be more elegant than this.
The second solution could look like this, but i don't have an implementation:
myStruct.setFields(field1:10, field2:0.5, field5:"hello");