digitalmars.D.learn - Idiomatic way to call base method in generic code
- ZombineDev (39/39) May 24 2015 import std.stdio, std.conv, std.traits;
- ZombineDev (13/14) May 24 2015 Small correction for clarity:
- ketmar (9/13) May 25 2015 i don't know why you want that, but something like this may do:
- ZombineDev (46/56) May 25 2015 Thanks!
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 24 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 =3D 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=20 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:You might be interested in this thread: http://forum.dlang.org/thread/mi3pip$22va$1 digitalmars.comi 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 Mon, 25 May 2015 09:24:56 +0000, ZombineDev wrote:On Monday, 25 May 2015 at 07:57:49 UTC, ketmar wrote:note that this funny trick works even for `void` methods, due to magic of=20 `auto` return type.=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 =3D BaseClassesTuple!(C)[0]; return mixin(`self.`~FSC.stringof~`.`~MTN~"(args)"); } writeln(d.callBaseMethod!"toString");Thanks!
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; } =20 struct Line2 { Point2 start; Point2 end; =20 mixin Access; =20 // alias x1 =3D this.start.x; <- this doesn't work :( =20 alias x1 =3D get!"start.x"; alias y1 =3D get!"start.y"; alias x2 =3D get!"end.x"; alias y2 =3D get!"end.y"; } =20 // 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=20 implemented that feature yet", of course).=
May 25 2015