Thread overview
Idiomatic way to call base method in generic code
May 24, 2015
ZombineDev
May 24, 2015
ZombineDev
May 25, 2015
ketmar
May 25, 2015
ZombineDev
May 25, 2015
Meta
May 25, 2015
ketmar
May 25, 2015
ketmar
May 24, 2015
import std.stdio, std.conv, std.traits;

class Base
{
    int x;
    override string toString() const
    {
        return x.to!string;
    }
}

class Derived : Base
{
    int y;
    override string toString() const
    {
        return y.to!string;
    }
}

void callMethod(T, alias Method)(const T thiz)
{
    thiz.fun();
}

void callBaseMethod(SubClass, alias Method)(const SubClass thiz)
{
    alias FirstSuperClass = BaseClassesTuple!(SubClass)[0];
    thiz.FirstSuperClass.Method();
}

void main()
{
    Derived d = new Derived();
    d.y = 15; d.x = 13;

    // 1) callMethod!(Derived, Derived.toString)(d);
    // 2) callBaseMethod!(Derived, Derived.toString)(d);
    // 3) writeln(d.Base.toString());

}


I know I can call a base implementation of a method like in 3), but I need to do it generically like in 2). Does anybody now how I can achieve this?
Additionally is there a way to make 1) work without using string mixins?
May 24, 2015
On Sunday, 24 May 2015 at 23:32:52 UTC, ZombineDev wrote:
> ...

Small correction for clarity:
void main()
{
    Derived d = new Derived();
    d.x = 13;
    d.y = 15;

    // 1) writeln(callMethod!(Derived, Derived.toString)(d)); <- Should print 15
    // 2) writeln(callBaseMethod!(Derived, Derived.toString)(d)); <- Should print 13
    // 3) writeln(d.Base.toString()); <- Prints 13
}
May 25, 2015
On Sun, 24 May 2015 23:32:50 +0000, ZombineDev wrote:

> I know I can call a base implementation of a method like in 3), but I need to do it generically like in 2). Does anybody now how I can achieve this?

i don't know why you want that, but something like this may do:

auto callBaseMethod(string MTN, C, Args...) (inout C self, Args args) {
  alias FSC = BaseClassesTuple!(C)[0];
  return mixin(`self.`~FSC.stringof~`.`~MTN~"(args)");
}

writeln(d.callBaseMethod!"toString");


> Additionally is there a way to make 1) work without using string mixins?

no. and again, why do you want that? why do you people are so afraid of string mixins? ;-)

May 25, 2015
On Monday, 25 May 2015 at 07:57:49 UTC, ketmar wrote:
> i don't know why you want that, but something like this may do:
>
> auto callBaseMethod(string MTN, C, Args...) (inout C self, Args args) {
>   alias FSC = BaseClassesTuple!(C)[0];
>   return mixin(`self.`~FSC.stringof~`.`~MTN~"(args)");
> }
>
> writeln(d.callBaseMethod!"toString");
>

Thanks!

[1]: https://github.com/ZombineDev/Chess2RT/blob/c36ba3e73744cf3912c25abccedbbd742f7f5be3/source/util/prettyprint.d#L7

[2]: https://github.com/ZombineDev/Chess2RT/blob/master/source/util/prettyprint.d#L14

I initially had [1] a string mixin which goes through all the members of a class and prints them and also prints its base class' members, but then it seemed that it would be more cleaner if I could use a function template [2] (which also improved my debug experience) so I started exploring alias, but they turned out to be less powerful then I thought:

alias can't refer to a nested member:
-------------
struct Point2
{
    float x;
    float y;
}

struct Line2
{
    Point2 start;
    Point2 end;

    mixin Access;

    // alias x1 = this.start.x; <- this doesn't work :(

    alias x1 = get!"start.x";
    alias y1 = get!"start.y";
    alias x2 = get!"end.x";
    alias y2 = get!"end.y";
}

// I need to use a mixin to flatten the access :(
private mixin template Access()
{
    ref auto get(string accessPattern)() inout
    {
        return mixin(accessPattern);
    }
}
-------------

So I wondered if I'm missing something and decided to ask here.

> no. and again, why do you want that? why do you people are so afraid of
> string mixins? ;-)

Well I'm not afraid of string mixins, but the `alias` keyword seemed to possess some mysterious power (I was also under the influence of this [3] blog post) which I wanted to explore. Also they're a bit more elegant.

[3]: http://blog.thecybershadow.net/2015/04/28/the-amazing-template-that-does-nothing/

May 25, 2015
On Monday, 25 May 2015 at 09:24:58 UTC, ZombineDev wrote:
> On Monday, 25 May 2015 at 07:57:49 UTC, ketmar wrote:
>> i don't know why you want that, but something like this may do:
>>
>> auto callBaseMethod(string MTN, C, Args...) (inout C self, Args args) {
>>  alias FSC = BaseClassesTuple!(C)[0];
>>  return mixin(`self.`~FSC.stringof~`.`~MTN~"(args)");
>> }
>>
>> writeln(d.callBaseMethod!"toString");
>>
>
> Thanks!
>
> [1]: https://github.com/ZombineDev/Chess2RT/blob/c36ba3e73744cf3912c25abccedbbd742f7f5be3/source/util/prettyprint.d#L7
>
> [2]: https://github.com/ZombineDev/Chess2RT/blob/master/source/util/prettyprint.d#L14
>
> I initially had [1] a string mixin which goes through all the members of a class and prints them and also prints its base class' members, but then it seemed that it would be more cleaner if I could use a function template [2] (which also improved my debug experience) so I started exploring alias, but they turned out to be less powerful then I thought:
>
> alias can't refer to a nested member:
> -------------
> struct Point2
> {
>     float x;
>     float y;
> }
>
> struct Line2
> {
>     Point2 start;
>     Point2 end;
>
>     mixin Access;
>
>     // alias x1 = this.start.x; <- this doesn't work :(
>
>     alias x1 = get!"start.x";
>     alias y1 = get!"start.y";
>     alias x2 = get!"end.x";
>     alias y2 = get!"end.y";
> }
>
> // I need to use a mixin to flatten the access :(
> private mixin template Access()
> {
>     ref auto get(string accessPattern)() inout
>     {
>         return mixin(accessPattern);
>     }
> }
> -------------
>
> So I wondered if I'm missing something and decided to ask here.
>
>> no. and again, why do you want that? why do you people are so afraid of
>> string mixins? ;-)
>
> Well I'm not afraid of string mixins, but the `alias` keyword seemed to possess some mysterious power (I was also under the influence of this [3] blog post) which I wanted to explore. Also they're a bit more elegant.
>
> [3]: http://blog.thecybershadow.net/2015/04/28/the-amazing-template-that-does-nothing/

You might be interested in this thread:

http://forum.dlang.org/thread/mi3pip$22va$1@digitalmars.com
May 25, 2015
On Mon, 25 May 2015 09:24:56 +0000, ZombineDev wrote:

> On Monday, 25 May 2015 at 07:57:49 UTC, ketmar wrote:
>> i don't know why you want that, but something like this may do:
>>
>> auto callBaseMethod(string MTN, C, Args...) (inout C self, Args args) {
>>   alias FSC = BaseClassesTuple!(C)[0];
>>   return mixin(`self.`~FSC.stringof~`.`~MTN~"(args)");
>> }
>>
>> writeln(d.callBaseMethod!"toString");
>>
>>
> Thanks!

note that this funny trick works even for `void` methods, due to magic of `auto` return type.

May 25, 2015
On Mon, 25 May 2015 09:24:56 +0000, ZombineDev wrote:

> alias can't refer to a nested member:
> -------------
> struct Point2 {
>      float x;
>      float y;
> }
> 
> struct Line2 {
>      Point2 start;
>      Point2 end;
> 
>      mixin Access;
> 
>      // alias x1 = this.start.x; <- this doesn't work :(
> 
>      alias x1 = get!"start.x";
>      alias y1 = get!"start.y";
>      alias x2 = get!"end.x";
>      alias y2 = get!"end.y";
> }
> 
> // I need to use a mixin to flatten the access :(
> private mixin template Access()
> {
>      ref auto get(string accessPattern)() inout {
>          return mixin(accessPattern);
>      }
> }
> -------------

i wonder if there is a reason for that limitation (except "nobody implemented that feature yet", of course).