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.)

Reply via email to