The most awesome "forward to member" solution?

Andrei Alexandrescu via Digitalmars-d digitalmars-d at puremagic.com
Sun May 3 13:09:59 PDT 2015


On 5/3/15 11:54 AM, Andrei Alexandrescu wrote:
> On 5/3/15 12:18 AM, Meta wrote:
>> On Sunday, 3 May 2015 at 05:49:52 UTC, Andrei Alexandrescu wrote:
>>> On 5/2/15 10:00 PM, Meta wrote:
>>>> It seems like it'd be a lot cheaper and cleaner to just be able to
>>>> alias
>>>> the parent method.
>>>
>>> Yeh, that's the first solution that comes to mind. alias doesn't work
>>> here but of course we could change the language.
>>>
>>>> Also, it could probably be made a bit simpler with
>>>> opDispatch.
>>>
>>> I'd have to see the code, but my intuition is that things could get
>>> quite a bit more hairy.
>>>
>>>
>>> Andrei
>>
>> IMO, using __traits and opDispatch is a fair bit cleaner, and I prefer
>> the syntax of a mixin template to regular mixin.
>>
>> http://dpaste.dzfl.pl/d60498246577
>
> You're right, that is lovely! I've improved it as follows:
>
> mixin template forwardToMember(alias member, methods...)
> {
>      import std.algorithm : among;
>      import std.traits : ParameterTypeTuple;
>      template opDispatch(string sym)
>      if ((methods.length == 0 || sym.among(methods)))
>      {
>          auto ref opDispatch(
>              ParameterTypeTuple!(__traits(getMember, member, sym)) args)
>          {
>              return __traits(getMember, member, sym)(args);
>          }
>      }
> }
>
> So now ref returns are preserved and the mixin is self-contained
> (doesn't require imports from the outside).
>
> Compared to my solution, this has the advantage that if the child
> defines a method, it will take precedence over the formatted one. So
> that allowed me to add a feature: if no methods are specified, all are
> forwarded.
>
> There are a couple of ways in which this could and should be improved,
> most notably overloads control. Even as is it's pretty darn awesome,
> Meta could you please make it into a pull request? I think it should go
> in std.functional.

Take that back, the opDispatch-based solution has a fatal flaw: doesn't 
compose properly. For example, in std.allocator it's frequent that 
allocators stack on top of one another, so one forwards a method call to 
another one which in turn forwards to another.

With code generation this obviously works out of the box because the 
generated code is identical to what one would write by hand to achieve 
the same. But the opDispatch-based solution only works one level.


Andrei



More information about the Digitalmars-d mailing list