On 5/30/20 11:28 PM, mw wrote:
On Sunday, 31 May 2020 at 00:46:09 UTC, Paul Backus wrote:
You can simplify this considerably using a mixin template [1]:
---
mixin template RW(T, string name) {
private T var;
public T get() { return var; }
public typeof(this) set(T val) { var = val; return this; }
mixin("private alias _", name, " = var;");
// two aliases with the same name create an overload set
mixin("public alias ", name, " = get;");
mixin("public alias ", name, " = set;");
}
class Point {
mixin RW!(int, "x");
mixin RW!(int, "y");
mixin RW!(string, "z"); // add
}
---
This is better, ... but it breaks std.traits:
The following code solves that I think the following syntax is an
improvement over Paul Backus's solution because it allows .x instead of
"x" by taking advantage of a static opDispatch. But it requires
parenthesis because now it's a string mixin, which is likely to be
noticeably slow to compile too.
struct RW(T) {
static string opDispatch(string name)() {
import std.format;
return format!q{
private %s _%s;
public auto %s() { return _%s; }
public auto %s(%s val) { _%s = val; return this; }
}(T.stringof, name,
name, name,
name, T.stringof, name);
}
}
struct Point {
mixin (RW!int.x);
mixin (RW!int.y);
// etc.
}
import std.traits;
import std.stdio;
void main() {
pragma(msg, FieldNameTuple!(Point));
auto p = Point(1, 2);
p.x = 42;
p.y = 43;
writeln(p);
}
The spec allows opDispatch to be an eponymous template:
https://dlang.org/spec/operatoroverloading.html#dispatch
Unfortunately, I could not reach the following cleaner syntax with a
mixin template:
mixin RW!int.x;
Ali