How do I set a class member value by its name in a string?
Biotronic
simen.kjaras at gmail.com
Wed Dec 27 23:47:14 UTC 2017
On Wednesday, 27 December 2017 at 21:42:53 UTC, Mengu wrote:
> On Wednesday, 27 December 2017 at 21:39:49 UTC, Mengu wrote:
>> On Wednesday, 27 December 2017 at 20:54:17 UTC, bitwise wrote:
>>> [...]
>>
>> there's also a simple workaround for fields with the same
>> type: https://run.dlang.io/is/dsFajq
>>
>> import std.stdio;
>>
>> struct S {
>> int x;
>> int y;
>> }
>>
>> auto setValue(ref S s, string field, int value) {
>> foreach (fieldName; __traits(allMembers, S)) {
>> if (fieldName == field) {
>> __traits(getMember, s, fieldName) = value;
>> break;
>> }
>> }
>> }
>>
>> void main() {
>> S s;
>> s.setValue("x", 5);
>> s.setValue("y", 25);
>> writeln(s);
>> }
>>
>>
>> you can play with it to make it more generic. you can also
>> create a mixin template that would generate setters for each
>> field you would need a setter for and then in the run time
>> you'd just be able to call them.
>
> return type should just be void. that's just my muscle memory.
> :-D
More generic, for more better:
void setValue(T, V)(auto ref T aggregate, string field, V value)
{
import std.traits : FieldNameTuple;
import std.meta : Alias;
switch (field)
{
foreach (fieldName; FieldNameTuple!T)
{
case fieldName:
static if (is(typeof(__traits(getMember,
aggregate, fieldName) = value)))
{
__traits(getMember, aggregate, fieldName) =
value;
return;
}
else assert(false, T.stringof ~ "."~field~"
cannot be assigned from a "~V.stringof~".");
}
default:
assert(false, T.stringof ~ " has no field named
"~field~".");
}
}
unittest {
import std.exception : assertThrown;
import core.exception : AssertError;
static struct S {
int x;
string s;
}
S s;
s.setValue("x", 14);
assert(s.x == 14);
assertThrown!AssertError(s.setValue("q", 14));
assertThrown!AssertError(s.setValue("s", 14));
s.setValue("s", "abc123");
assert(s.s == "abc123");
}
unittest {
import std.exception : assertThrown;
import core.exception : AssertError;
static class C {
int x;
string s;
}
C c = new C;
c.setValue("x", 14);
assert(c.x == 14);
assertThrown!AssertError(c.setValue("q", 14));
assertThrown!AssertError(c.setValue("s", 14));
c.setValue("s", "abc123");
assert(c.s == "abc123");
(new C).setValue("x", 143);
}
--
Biotronic
More information about the Digitalmars-d-learn
mailing list