Boost logo

Boost :

From: Jesse Jones (jesjones_at_[hidden])
Date: 2004-09-22 00:45:10


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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk