2

This is a question regarding how Multiple Dispatch works.

Suppose that we have a type hierarchy like this:

Drawable -> Shape -> Polygon -> Rectangle

And there are three functions (This is a pseudo-code):

void func(Rectangle*, Drawable*, Drawable*) ...
void func(Rectangle*, Rectangle*, Drawable*) ...
void func(Polygon*, Rectangle*, Rectangle*) ...

And suppose that this is a piece of code:

Drawable* x = create_rectangle();
Drawable* y = create_rectangle();
Drawable* z = create_rectangle();

Obviously types of x,y,z are all Drawable but they contain instances of a Rectangle. Which function will be called if I write: func(x, y, z)?

We don't have any function which matches exact types of x, y and z so what happens in this case?

Mahdi
  • 179
  • 5

2 Answers2

2

You can implement this several ways. The way that would be least surprising to me is to prefer the least abstract match and to look for it from left to right.

In this case that means you'd call:

void func(Rectangle*, Rectangle*, Drawable*) ...
candied_orange
  • 102,279
  • 24
  • 197
  • 315
  • What if there are multiple such candidates? e.g. `func(Rect, Rect, Drawable)` and `func(Drawable, Rect, Rect)`? – Mahdi May 17 '17 at 15:07
  • 2
    Then it's an ambiguity error. – Jörg W Mittag May 17 '17 at 15:25
  • 4
    Rect is less abstract then Drawable so f(RRD) wins over f(DRR) because you check this from left to right. It's just like sorting one column before another or simple alphabetizing. – candied_orange May 17 '17 at 15:33
  • 1
    Be aware, the simple left to right scheme works well right up until you decide you want to allow named parameters, because suddenly calls don't have positional information you can trust. – candied_orange May 17 '17 at 19:33
  • 1
    Well, you could still use arbitrary disambiguation rules, even with named paramaters: left-to-right declaration order in the parameter list, left-to-right passing order in the argument list, lexicographic ordering of the names, etc. The question is: should you? Is an arbitrary disambiguation rule better than a compile error? (My opinion is: no.) – Jörg W Mittag May 18 '17 at 15:45
  • @JörgWMittag well to me the nature of the problem is usability. The harder it is to keep a rule straight in your head the less useful it is when what you're trying to do is abstraction. Doesn't help that we're losing interest in inheritance anyway. – candied_orange May 18 '17 at 15:59
  • That's what I hinted at with my "should you?" question. If you allow overloading on types, then the overload resolution should be based solely on types. Basing it on the order of parameters, or the order of arguments, or the lexicographic ordering of parameter identifiers, or whatever, has nothing to do with what you want your overload resolution to accomplish. It's an arbitrary rule for disambiguating a situation which is inherently ambiguous. If the situation is inherently ambiguous, it's much better to have a compiler error than an arbitrary rule, IMO. – Jörg W Mittag May 21 '17 at 11:22
  • @JörgWMittag It can be confusing yes but left to right ordering is what lets us resolve multiple inheritance ambiguities, order of operations, and read English. So while it's arbitrary it's not surprising. My concern with named parameters was that it can scramble this sense of left to right ordering. Mostly because I can't decide if the declaration or the call should decide the ordering. Without named parameters these are the same thing. – candied_orange May 21 '17 at 11:36
1

I can't speak for other languages, but given your posted code,

func(x, y, z);

is an error in C++.

See http://ideone.com/cEJyfA.

If you decide to implement dynamic dispatch based on multiple arguments, you'll have to build the algorithm yourself. If you do that, one sensible strategy would be to use the best matching function based on the type of the object the arguments point to, from left to right.

If you are able to implement such a mechanism,

func(x, y, z);

should ultimately call:

void func(Rectangle*, Rectangle*, Drawable*);
R Sahu
  • 1,966
  • 10
  • 15