digitalmars.D.learn - Overloading free functions & run-time dispatch based on parameter types
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (37/37) Feb 05 2016 From the docs:
- Nicholas Wilson (3/10) Feb 05 2016 sounds like foo should just be a method in the class rather than
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (6/8) Feb 05 2016 In my particular case I want to keep some stuff outside of claases.
- Marc =?UTF-8?B?U2Now7x0eg==?= (26/26) Feb 05 2016 Does the following help?
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (35/37) Feb 05 2016 I thought about it too, but I need it to work with more then one
- Marc =?UTF-8?B?U2Now7x0eg==?= (16/46) Feb 06 2016 I don't see why this wouldn't work, if you've in fact covered all
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (11/28) Feb 07 2016 It works, the problem was that castSwitch returns something and I
From the docs: class A { } class B : A { } class C : B { } void foo(A); void foo(B); void test() { C c; foo(c); // calls foo(B) } I need the other way around. So, at runtime I get an A and depending on it's dynamic type, I would like to get the correct foo() called. class A { } class B : A { } class C : A { } void foo(B); void foo(C); void test() { B b; A a = b: foo(a); // should call foo(B) } When doing something like this in my code I get the following compile error (message adapted to match pseudo-code): source/app.d(751): Error: None of the overloads of 'foo' are callable using argument types (A), candidates are: source/app.d(742): app.foo(B) source/app.d(746): app.foo(C) I hope the problem is understandable. Is there a way to dispatch a call to the correct free functions based on the run-time type of the arguments without writing a switch or so? -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Feb 05 2016
On Friday, 5 February 2016 at 10:54:27 UTC, Robert M. Münch wrote:From the docs: class A { } class B : A { } class C : B { } void foo(A); void foo(B); [...]sounds like foo should just be a method in the class rather than a free function
Feb 05 2016
On 2016-02-05 11:10:36 +0000, Nicholas Wilson said:sounds like foo should just be a method in the class rather than a free functionIn my particular case I want to keep some stuff outside of claases. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Feb 05 2016
Does the following help? import std.algorithm.comparison : castSwitch; import std.stdio; class A { } class B : A { } class C : A { } auto foo_impl(B b) { writeln("called foo(B)"); } auto foo_impl(C c) { writeln("called foo(C)"); } auto foo(A a) { return a.castSwitch!( (B b) => foo_impl(b), (C c) => foo_impl(c), ); } void main() { B b = new B(); A a = b; foo(a); // called foo(B) } With a bit of template magic, you can make it DRY, e.g. alias foo = buildSwitch!foo_impl;
Feb 05 2016
On Friday, 5 February 2016 at 19:48:45 UTC, Robert M. Münch wrote:I thought about it too, but I need it to work with more then one parameter, so I tried this which doesn't work: Value nativePlus(Value a, Value b){ // not working, runtime exception castSwitch!( (IntV a) { castSwitch!( (IntV b) {return new IntV(a.num + b.num);} )(b); }, (StringV a) {return new StringV("string plus");}, )(a); // to keep compiler happy when using castSwitch (has no return statement) return new UnsetV(); }I don't see why this wouldn't work, if you've in fact covered all combinations. One thing that tripped my up was a null references - these are never castable to anything, not even Object. If not all combinations are valid, you can add a lambda that accept Value (or even Object), which is called as a "default" branch.and ended with this, which works and is straight forward but maybe not that elegant: Value nativePlus(Value a, Value b){ if(cast(IntV) a && cast(IntV) b) return new IntV((cast(IntV)a).num + (cast(IntV)b).num); if(cast(StringV) a && cast(StringV) b) return new StringV((cast(StringV)a).str ~ (cast(StringV)b).str); // if no case was hit (could throw) return new UnsetV(); } Can this be written simpler or more elegant?It's similar to how castSwitch is implemented, though the double casts are inefficient. You could use: if(auto inta = cast(IntV) a) { if(auto intb = cast(IntV) b) { return new IntV(inta.num + intb.num); } } (Again, this can be automated.)I read this here: https://github.com/D-Programming-Language/phobos/pull/1266#i suecomment-53507509 (functional pattern matching) but it seems it won't be implemented... at the end of the day what I simulate are poor-mans-multimethodsAs I read the discussion, it was just decided to defer the more complex version of castSwitch for later, but it wasn't rejected.Feb 06 2016