Multiple dispatch is trivial in C++ using overloaded functions, the compiler will select the most specialized version for the supplied parameters without any visitor tricks. The "problem" is that it doesn't play well with polymorphism since it can't trigger specialized overloads for base class pointers/references, I think the real problem is polymorphism.
That only works for statically visible options. More, it isn't "multiple dispatch. It is a single one, chosen by the compiler. The article shows how to get the right behavior at runtime. Where there are two dispatches in order to get the right behavior.
That's not what multiple dispatch used to mean, it used to be about dispatching on multiple arguments. Like I said, it doesn't cover all bases; but when it works it beats over-engineered bullshit like this.
I'd be interested in sources. I can see how method overloading looks like multiple dispatch, but again, it only works on static information.
If you want a collection of items where you call a different overloaded method on each, you are either checking the type of each one manually, or you are doing something like this.
Overloading is dispatching based on types of multiple arguments. If someone adds a more specialized overload, it will be called instead of the existing. The problem is dispatching on polymorphic types. As long as you still have your Squares and Circles intact, the right function will be called. And in C++, keeping the concrete types intact as far as possible is a solid strategy.
For your collection example, at some point you need to introduce some kind of polymorphism to get back to concrete types; but once you're back, overloading works just fine again. The best strategy to recover types depends too much on specifics to be formalized.
I'm aware of what the difference is. But, and this is really important, you cannot gloss over the static nature of overloaded methods. You say "if someone adds a more specialized overload, it will be called", but that is only true if they recompile.
Generic functions in LISP are another way of doing this. It works at runtime, as well. And that leads to a good article in the elisp manual (https://www.gnu.org/software/emacs/manual/html_node/elisp/Ge...) that shows multiple dispatch being a runtime thing even way back. So, again, I'd be interested to know sources that said multiple dispatch was the same as method overloading.
I think I can see where overloaded methods were likely coopted by single dispatch statically compiled languages. But, honestly, I don't see how "multiple dispatch" would have ever made sense in those cases, either.
No one said a recompile wasn't allowed, plenty of things aren't possible in C++ without a recompile. All I'm saying here is that when you don't need polymorphism, which should be most of the time; overloaded functions do the same thing.
What folks are saying is that if it is a single dispatch, but based on the parameters, it is not multiple dispatch. Literally count the number of dispatches. If it is a single, it is not multiple.
I'm somewhat goal shifting by pointing out that with this you can get dynamic behavior without a full recompile, but really only a little. The entire point of this behavior is that the link in to the method is statically known to a point that can then do another dispatch where it will go to the correct place.
The visitor pattern is a somewhat ugly way of accomplishing this, true. But it is absolutely more powerful than method overloading.
https://docs.julialang.org/en/stable/manual/methods/