Skip to content

Instantly share code, notes, and snippets.

@Biotronic
Last active March 14, 2018 23:26
Show Gist options
  • Save Biotronic/5849af011cbe9c7ea05515011d5995bf to your computer and use it in GitHub Desktop.
Save Biotronic/5849af011cbe9c7ea05515011d5995bf to your computer and use it in GitHub Desktop.
Library-only properties in D
struct S {
int n;
mixin property!("field", "get => this.n", "set => this.n = set");
}
unittest {
import std.conv : to;
S s;
s.field = 3;
assert(s.field == 3);
s.field += 2;
assert(s.field == 5);
s.field++;
assert(s.field == 6);
assert(s.field.to!string == "6");
}
import std.meta;
import std.traits;
import std.array;
import std.conv;
mixin template property(string name, fns...) {
mixin(propertyImpl!(name, fns));
}
string propertyImpl(string name, fns...)() {
string[] s;
static foreach (i; 0..fns.length) {
static if (is(typeof(fns[i]) == string)) {
s ~= "mixin(fns["~i.to!string~"])";
} else {
s ~= "fns["~i.to!string~"]";
}
}
string typename = "Property!("~s.join(", ")~")";
return "auto "~name~" () { return "~typename~"(); }"~
"auto "~name~"(T)(T value) { return "~typename~"(value); }";
}
template functionName(alias fn, T = DummyType) {
alias fun = fn!T;
static if (is(FunctionTypeOf!fun PT == __parameters)) {
enum functionName = __traits(identifier, PT);
}
}
struct DummyType {}
struct Property(fns...) {
alias getter = findFunction!("get", DummyType, fns);
alias setter = findFunction!("set", ReturnType!getter, fns);
this(T)(T value) {
setter(value);
}
auto get() { return getter(DummyType.init); }
alias get this;
auto opAssign(T)(T rhs) {
return setter(rhs);
}
auto opOpAssign(string op, T)(T rhs) {
return setter(opFun!op(getter(DummyType.init), rhs));
}
auto opUnary(string op)() {
auto tmp = getter(DummyType.init);
return setter(mixin(op~"tmp"));
}
string toString() {
import std.conv;
return get.to!string;
}
}
template findFunction(string name, T, fns...) {
static if (fns.length == 0) {
alias findFunction = void;
} else static if (functionName!(fns[0], T) == name) {
alias findFunction = Instantiate!(fns[0], T);
} else {
alias findFunction = findFunction!(name, T, fns[1..$]);
}
}
template opFun(string op) {
auto opFun(T1, T2)(T1 lhs, T2 rhs) {
mixin("return lhs "~op~" rhs;");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment