On Wednesday, 14 June 2017 at 09:34:27 UTC, Balagopal Komarath wrote:
void main()
{
        Test!Duck d;
}

As has been pointed out at length by others here, it's simply not how alias this is intended to work. I do see some arguments in favor of working that way, but I'm not sure what's the right solution.

Anyways, there is another solution - we could write a template that does the conversion for us. There is std.typecons.Proxy, which seems like a good fit, however it doesn't work quite the way we want. Here however, is a solution that works for simple examples. It might work for more complex examples as well, but I simply haven't tested that:

template duckImpl(alias a, TI, Fns...) {
    static if (Fns.length > 0) {
        mixin duckImpl!(a, TI, Fns[1..$]);

        alias thisFn = Fns[0];
        enum string fnName = __traits(identifier, thisFn);

mixin("ReturnType!thisFn "~fnName~"(Parameters!thisFn args) { return a."~fnName~"(args); }");
    }
}

template duck(TI) if (is(TI == interface)) {
    TI duck(T)(T t) {
        import std.meta;
        import std.traits;

        template Functions(string s) {
            alias Functions = MemberFunctionsTuple!(TI, s);
        }

        static class Result : TI {
            private T payload;
            this(T value) {
                payload = value;
            }
mixin duckImpl!(payload, TI, staticMap!(Functions, __traits(allMembers, TI)));
        }
        return new Result(t);
    }
}

interface I {
    void bar();
}

struct S {
    void bar() {
        import std.stdio;
        writeln("OHAI");
    }
}

unittest {
    I i = S().duck!I;
    i.bar();
}

--
  Biotronic

Reply via email to