On Monday, 18 January 2016 at 18:08:31 UTC, tsbockman wrote:
Again, I can probably automate generation of the wrapper easily
enough.
Genericized:
template acceptRVals(alias func) {
private:
import std.traits : arity;
alias impl = acceptRVals!(arity!func);
public:
alias acceptRVals = impl!func;
}
template acceptRVals(size_t arity) {
private enum mixStr = function() {
import std.conv : to;
string ctParams = "";
string rtParams = "";
string callArgs = "";
foreach(size_t a; 0 .. arity) {
string aStr = a.to!string;
ctParams ~= "T" ~ aStr;
rtParams ~= "auto ref T" ~ aStr ~ " a" ~ aStr;
callArgs ~= "a" ~ aStr;
if(a < (arity - 1)) {
ctParams ~= ", ";
rtParams ~= ", ";
callArgs ~= ", ";
}
}
return "pragma(inline, true) auto acceptRVals(" ~
ctParams ~ ")(" ~ rtParams ~ ") { return func(" ~ callArgs ~ ");
}";
}();
template acceptRVals(alias func) {
mixin(mixStr);
}
}
struct CustomString {
this(string data) {
this.data = data;
}
string data;
alias data this;
}
import std.stdio;
alias func = acceptRVals!(function(ref CustomString s1, ref
CustomString s2) {
writeln(s1);
writeln(s2);
s2 = "universe!";
});
void main() {
CustomString b = CustomString("world!");
func(CustomString("Hello"), b);
writeln("Hello");
writeln(b);
}
(I'm sure there are various corner cases not handled properly by
this; obviously it would be nice if this was just handled
automatically by the compiler like it should be.)