Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
May 24, 2015 Idiomatic way to call base method in generic code | ||||
---|---|---|---|---|
| ||||
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 Re: Idiomatic way to call base method in generic code | ||||
---|---|---|---|---|
| ||||
Posted in reply to ZombineDev | 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 Re: Idiomatic way to call base method in generic code | ||||
---|---|---|---|---|
| ||||
Posted in reply to ZombineDev Attachments: | 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 Re: Idiomatic way to call base method in generic code | ||||
---|---|---|---|---|
| ||||
Posted in reply to ketmar | 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 Re: Idiomatic way to call base method in generic code | ||||
---|---|---|---|---|
| ||||
Posted in reply to ZombineDev | 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 Re: Idiomatic way to call base method in generic code | ||||
---|---|---|---|---|
| ||||
Posted in reply to ZombineDev Attachments: | 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 Re: Idiomatic way to call base method in generic code | ||||
---|---|---|---|---|
| ||||
Posted in reply to ZombineDev Attachments: | 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).
|
Copyright © 1999-2021 by the D Language Foundation