Implementing interfaces using alias this

Biotronic via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jun 15 00:12:56 PDT 2017


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


More information about the Digitalmars-d-learn mailing list