
On Sep 20, 2004, at 11:25 AM, Lassi A.Tuura wrote:
You might also want to take a look at a multi-method implementation I have written several years ago for comparison. I would definitely love to see a (de facto or real) standard multi-method implementation. I never had the energy to pursue a full proposal to the C++ language committee.
There actually was a draft proposal. See <http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1529.html#1.1.1>.
I wrote my implementation to prove that this could be done in a compiler and thus could be integrated into the language. It is definitely not optimal to do it in a library as everyone probably knows.
No, it's not optimal, but you can do surprisingly well with templates and typeid. Although better support for type reflection would help...
Our implementation is not completely in the template coding style of boost, but as far as multi-methods go, it has been sufficiently capable for our needs; the main client has been a visualisation system I can describe in more detail if necessary. The front-end interface to developers uses a couple of macros, not templates. The macros are designed to give a feel of normal function definitions, but there are syntax limitations. Macros were chosen because a "nice" interface using templates simply didn't work across a variety of compilers -- both compile-time and run-time issues cropped up. Templates might work today fine; the macros do make fair use of templates internally already.
It's interesting code, although the macros are a bit of a turn-off. :-)
Back to the core matter. Features: 1) practically everything is at run-time, no compile-time limits or restrictions 2) no dispatch-time memory allocation (except if the method family has changed, see point 6) 3) any polymorphic class can be used as such for dispatching, no need to touch the participating classes in any way 4) handles real polymorphic calls, no need to have an exact match
I do all this, although the code doesn't optimize dispatch as of yet.
5) supports arbitrary number of polymorphic arguments, including just one (the macro and template sugar on top is more restricted); arguments used in dispatch must be pointers to polymorphic types, and can't be null pointers at call time
I have a base class that handles the complex logic and relatively simple derived classes for different arities. There are no restrictions on argument types except that method formal arguments can't be non-const references (there's special case code for const references since they're difficult to handle with typeid). Fundamental types are matched using the normal rules so a promotion is better than a conversion for example.
6) supports arbitrary number of non-polymorphic arguments (actually limitation of the top syntax sugar layer, the dispatch engine only sees arguments used in dispatch); arguments not used in dispatch can be of any type, including scalars
I don't do this:: all of the arguments participate in dispatch. One possible optimization is for the dispatch code to ignore arguments for which the methods all use the same non-polymorphic type. I also have an any_type for multimethods that can accept any value for a particular argument.
7) handles dynamic changes the method family at run-time: it's ok to dynamically load and unload members of the family at any time
I can dynamically add methods, but I don't support removing methods. Seems like a good idea though and easy to implement so I've added it to my list.
8) multi-methods can be globals or class (static) members; they are objects with operator() overload, not functions 9) the member functions of a multi-method can be either free-floating (global) functions or class (static) member functions, independent of whether the multi-method itself was a global or class-static (modulo privacy rules)
Ditto: multimethods are just ordinary function objects and may even be copied. Methods can be any sort of function object (although the objects returned by boost::bind don't work since they don't have typedef's like first_argument_type. As a work-around you can assign them to boost::function objects which do work).
10) handles run-time ambiguity using the same rules as compile-time overload resolution, and refuses to make the call 11) supports large class hierarchies with several polymorphic arguments and several multimethods: doesn't compute the full dispatch matrix
Ditto.
Currently it doesn't support invoking the next dispatch method, and it isn't thread-safe, but both are quite simple to add and will be done when it becomes an issue. In fact, making it thread-safe will naturally add support for next method dispatch.
Mine isn't thread safe at the moment either. -- Jesse