Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
February 05, 2016 Overloading free functions & run-time dispatch based on parameter types | ||||
---|---|---|---|---|
| ||||
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
|
February 05, 2016 Re: Overloading free functions & run-time dispatch based on parameter types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert M. Münch | 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
|
February 05, 2016 Re: Overloading free functions & run-time dispatch based on parameter types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | 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 function In my particular case I want to keep some stuff outside of claases. -- Robert M. Münch http://www.saphirion.com smarter | better | faster |
February 05, 2016 Re: Overloading free functions & run-time dispatch based on parameter types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert M. Münch | 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; |
February 05, 2016 Re: Overloading free functions & run-time dispatch based on parameter types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | On 2016-02-05 15:23:53 +0000, Marc Schütz said: > Does the following help? > ... 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(); } 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? I read this here: https://github.com/D-Programming-Language/phobos/pull/1266#issuecomment-53507509 (functional pattern matching) but it seems it won't be implemented... at the end of the day what I simulate are poor-mans-multimethods -- Robert M. Münch http://www.saphirion.com smarter | better | faster |
February 06, 2016 Re: Overloading free functions & run-time dispatch based on parameter types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert M. Münch | 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#issuecomment-53507509 (functional pattern matching) but it seems it won't be implemented... at the end of the day what I simulate are poor-mans-multimethods As I read the discussion, it was just decided to defer the more complex version of castSwitch for later, but it wasn't rejected. |
February 07, 2016 Re: Overloading free functions & run-time dispatch based on parameter types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz Attachments:
| On 2016-02-06 14:33:57 +0000, Marc Schütz said: > I don't see why this wouldn't work, if you've in fact covered all combinations. It works, the problem was that castSwitch returns something and I didn't "catch" it. > 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); > } > } Yes, thanks. Was on my list. > (Again, this can be automated.) How? Do you mean by castSwitch? >> I read this here: https://github.com/D-Programming-Language/phobos/pull/1266#issuecomment-53507509 (functional pattern matching) but it seems it won't be implemented... at the end of the day what I simulate are poor-mans-multimethods > > As I read the discussion, it was just decided to defer the more complex version of castSwitch for later, but it wasn't rejected. Well... yes, "won't be implemented in the near future" Anyway, it's not available at the moment, so looking at other ways. -- Robert M. Münch http://www.saphirion.com smarter | better | faster |
Copyright © 1999-2021 by the D Language Foundation