
Hi, i'm on the verge of completing a first release of a fully featured multimethods component for C++, one in which i believe goes beyond anything currently available and is very suited to become part of boost. I'm fully aware of Jesse Jones's contribution however his library has not become an offical part of boost and i believe my version takes things much further in thew different ways and i have some nice ideas for the next version to make even better. It's inspired by boost/std::tr1::function and CLOS generic functions and thus works like bost::/std::tr1::function preferred syntax ALA function types e.g: typedef boost::shared_ptr<fuzz> fuzz_ptr; generic_function< void (const foo&, int, bar*, float, fuzz_ptr) > foobar; where foo, bar and fuzz are polymorphic types and automatically are considered for multiple dispatch, detection of which arguments are choosen for dispatch is automated (and yes there already is support for smart/proxy pointers/references in place with std::auto_ptr, boost::/std::tr1::shared/intrusive_ptr working out-the-box). The order and placement of arguments is irrelevant and non-polymorphic arguments are totally allowed, covariant return types comes for free and work similar to covariant return types of virtual member functions. I think i'll just stop writing about the library any further (abit more to it than this) i just like to know if you guys are interested in making this an offical part of boost and to be worked on further by myself and with the help of others. P.S By the way this has been built with boost mpl, preprocessor and type traits from the beginning and interlope with other boost components in mind i.e phoenix, lambda, fusion, bind, function etc, etc.

I recently had to implement something similar for a project I'm working on. I would certainly like to see something more complete than what I came up with placed in boost. -Fred On 3/1/06, Korcan Hussein <korcan_h@hotmail.com> wrote:
Hi, i'm on the verge of completing a first release of a fully featured multimethods component for C++, one in which i believe goes beyond anything currently available and is very suited to become part of boost. I'm fully aware of Jesse Jones's contribution however his library has not become an offical part of boost and i believe my version takes things much further in thew different ways and i have some nice ideas for the next version to make even better.
It's inspired by boost/std::tr1::function and CLOS generic functions and thus works like bost::/std::tr1::function preferred syntax ALA function types e.g:
typedef boost::shared_ptr<fuzz> fuzz_ptr;
generic_function< void (const foo&, int, bar*, float, fuzz_ptr) > foobar;
where foo, bar and fuzz are polymorphic types and automatically are considered for multiple dispatch, detection of which arguments are choosen for dispatch is automated (and yes there already is support for smart/proxy pointers/references in place with std::auto_ptr, boost::/std::tr1::shared/intrusive_ptr working out-the-box). The order and placement of arguments is irrelevant and non-polymorphic arguments are totally allowed, covariant return types comes for free and work similar to covariant return types of virtual member functions.
I think i'll just stop writing about the library any further (abit more to it than this) i just like to know if you guys are interested in making this an offical part of boost and to be worked on further by myself and with the help of others.
P.S By the way this has been built with boost mpl, preprocessor and type traits from the beginning and interlope with other boost components in mind i.e phoenix, lambda, fusion, bind, function etc, etc.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- F

"Korcan Hussein" <korcan_h@hotmail.com> writes:
I think i'll just stop writing about the library any further (abit more to it than this) i just like to know if you guys are interested in making this an offical part of boost and to be worked on further by myself and with the help of others.
Sounds fascinating; show me more! -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Korcan Hussein" <korcan_h@hotmail.com> writes:
I think i'll just stop writing about the library any further (abit more to it than this) i just like to know if you guys are interested in making this an offical part of boost and to be worked on further by myself and with the help of others.
Sounds fascinating; show me more!
Wow! Gimme gimme gimme! :) Cheers, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

"David Abrahams" <dave@boost-consulting.com> wrote in message news:<uslq1y4lo.fsf@boost-consulting.com>...
Sounds fascinating; show me more!
Heh, okay I still have a little way left to go but the "shell" of it is pretty much complete as well as most of the guts of it. Okay I'll try to elaborate a bit more about this. Lets start with what the client gets to play with, well you have a choice of two similar but different kinds of front-ends. The first and main one is (currently) called generic function (maybe it should change it to something like boost::generic::function instead?). This component allows any kind of C++ callable entity to be registered for dynamic dispatch, as you could probably guess it gets a little help from boost::function in this department :). quick example: // single dispatch generic_function< void (boost::shared_ptr<foo>, float) > print_foo; const bool reg[] = { print_foo.def_method< boost::shared_ptr<bar> >(print_bar), print_foo.def_method< boost::shared_ptr<fuzz> >(print_fuzz) }; ..... boost::shared_ptr<foo> foo_ptr(new fuzz); print_foo(foo_ptr, 0.0f); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // multiple dispatch ( farfetched example :) ) typedef float (my_sig)(const std::string&, const base1&, float, Base2*, std::string, boost::intrusive_ptr<base3>, base1**, Base2*&, wrap<const base3&>); // const base1&, Base2*, boost::intrusive_ptr<base3> are selected for dispatch, // base1**, Base2*&, wrap<const base3&> are not selected for very good reasons! // "wrap" is a trivial metafunction clients can use to disable the automated deduction. generic_function< my_sig > foobar; const bool reg[] = { foobar.def_method< const dev1_1&, dev2_1*, boost::intrusive_ptr<dev3_1>
(func_obj1),
foobar.def_method< const dev1_2&, dev2_2*, boost::intrusive_ptr<dev3_2>
(func_obj2),
foobar.def_method< const dev1_3&, dev2_3*, boost::intrusive_ptr<dev3_3>
(func_obj3)
}; Of-course you are not required to register functions all at once and this is completely non-intrusive solution, I'm just doing it here for illustrative purposes. As you can see the registration process is a little nasty (open to suggestions & debate), unfortunately because of pointer/reference *proxy* support CV qualification and raw pointer/reference is required, fortunately forgetful clients will be caught at compile-time :). Only sub-types are required to be stated and the reason they are required is it's not possible to deduce argument types of function objects however I could write an overload that can deduce types for free-functions ala boost::function_traits. As of current this is the only place where the order sub-types should come in the same order stated to generic_function but generic_function itself does not care for order and placement of arguments of polymorphic types, again mistakes will be caught out before they have a chance :). Now I'll briefly describe the other front-end called fast_generic_function for a lack of a better name the only difference it has from generic_function is it should have less overhead in terms of storage & runtime (but maybe slightly longer compile-time) because it deals solely with pointer to functions as opposed to boost::function, also "def_method" member function for fast_generic_function is used slightly different an example using the first example above would be: const bool reg[] = { print_foo.def_method< void (boost::shared_ptr<bar>, float), print_bar >(), print_foo.def_method< void (boost::shared_ptr<fuzz>, float), print_fuzz >() }; Both generic_function and fast_generic_function use the same backend called generic_functionN (this might change latter in into two classes generic_base_fun and generic_functionN but this is of no concern to clients), they are all parameterized by allocator type and default to use std::allocator of-course. As of current exact method matches are an (amortized) constant time operation, as you can pretty much guess a hash map is used that maps a tuple of type identifies to either function pointers or boost::function (depending on which front-end is used). I'm currently using boost::fusion::vector instead of boost::tuples/std::tr1::tuple because it's a bit more flexible to work with but I'm going to change it to use boost::tuples::tuple simply for the reason that boost::fusion isn't (yet) currently an official part of boost. Boost.Functional/Hash is also used. I'm going to investigate boost::multi_index_container as an alternative so there could be a possibility of (amortized) constant time exact matches and logarithmic time best matches. That is what I'm going to explore this weekend and adding method combinations (before, after around, call-next-method etc). Let me emphasize one thing I'm trying my utmost to keep compile-times and code bloat to the minimum as much as possible, taking advantage of lazy evaluation (lazy template instantiation) via MPL views where ever possible etc, etc. (Possible) Future directions I would like to see: support for boost::any, be the end for type-switching code on many anys ^_^, Move semantics, Further improve efficiency, Reduce compile-times further, Use "Multiple Row Displacement" algorithm, And the ultimate aim is to have support for Predicate dispatching in C++ if it's possible at all (highly doubt it). For those who don't know Predicate dispatching is a further generalization of multimethods with some ML pattern matching goodness. P.S. I forgot to mention this *as of current* RTTI support needs to be enabled, it's not as bad as it may sound, it is only required in one place and that is determining type identities via typeid operator at runtime this is the only decent way to make this solution non-intrusive and loosely coupled. Besides i've read that invoking the typeid operator is an amortized constant time operation however I cannot find any confirmation of this in the current C++ standard does anybody for sure?.

So what do you guys think thus far? anything you like/dislike and/or suggestions?.

"Korcan Hussein" wrote:
So what do you guys think thus far? anything you like/dislike and/or suggestions?.
Please put the library into Boost Vault: http://boost-consulting.com/vault/ I guess many are curious on it. /Pavel

Hiya, I've pretty much finished thus far with the shell (all the boost.mpl & boost.preprocessor side of it). I initially had a stub implementation using a hash map that maps a tuple of type identifiers to either a pointer to function or boost::function where a hashing was based off the string of the type identifier. This allowed for exact matches only so over the weekend I played around with idea of using boost::multi_index_container to allow me gain (amortized) constant time exact matches using hashed indices and logarithmic time inexact/nearest/best matches using ordered indices. After a thew attempts i've become pretty much stumped on getting best/nearest matches to work for all combinations correctly, there is always one odd case where the set of applicable methods leaves out a more correct/better method that is available. Also i'm not sure if this method would handle multiple/virtual inheritance correctly (i've not tried it yet). Another thing i relized was that hased indicies has issues of symmetric methods/functions (while ordered indicies of-course doesn't). So i was wondering if anyone can point me in the right direction or a give me hand on dealing with the best/nearest matches in conjunction with boost::multi_index_container or suggest another alternative. Once this bit is done i'll upload it to boost vault :). Thanks Korcan.

Korcan Hussein ha escrito: [...]
Another thing i relized was that hased indicies has issues of symmetric methods/functions (while ordered indicies of-course doesn't).
I don't know what you mean here.
So i was wondering if anyone can point me in the right direction or a give me hand on dealing with the best/nearest matches in conjunction with boost::multi_index_container or suggest another alternative.
Hello Korcan, I'm quite proficient in Boost.MultiIndex so maybe I can be of some help. Unfortunately, I'm not understading the explanation of your current probem, probably for lack of context. If you could provide me (either privately or through the list) with some more info and some code to have a look at, I can try to help. Best, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

"Joaquín Mª López Muñoz" <joaquin@tid.es> wrote in message news:440D86A5.532D8066@tid.es...
I don't know what you mean here.
I was just talking about symmetry of multimethods, say you had a generic function declaration such as: generic_function< void (const bar&, const bar&) > gen_fun; and you register a function like so: gen_fun.def_method< const foo&, const baz& >(fun); // where foo & baz are sub-types of bar Now say you have 2 variables to use with this generic function that have there arguments the other way round: baz b; foo b; gen_fun(b, f); Now the hashed indices view will not find a matching function because the original function registered was with a combined hashed of the type identifiers of foo then baz but the combined hash of the type identifiers of baz then foo is not the same hash value which makes sense. It's not a problem with boost::multi_index_container it's just a slight flaw in my logic :) It's not to much of a problem since an ordered view would still pick this up but it's not an (amortized) constant time operation it's logarithmic time.
I'm quite proficient in Boost.MultiIndex so maybe I can be of some help. Unfortunately, I'm not understading the explanation of your current probem, probably for lack of context. If you could provide me (either privately or through the list) with some more info and some code to have a look at, I can try to help.
Thanks, i think i've managed to sort it now, it's wasn't an issue of using boost::multi_index_container per-say. Now i've stumbed on another issue, originally the predicate function i was using for the keys of the ordered indices view was simply std::type_info::before but this causes some slight problems because std::type_info::before only gives a collating order of types, it does not tell you if one std::type_info instance is a sub/super-type of another only if one type proceeds another. I can't use type traits any more since this is dealing with the runtime world. I can't use dynamic_cast to make runtime type queries because I have std::type_info instances not static types. So does anybody know of a good method to determine if one std::type_info is a sub/super-type or another std::type_info.

"Korcan Hussein" <korcan_h@hotmail.com> writes:
So does anybody know of a good method to determine if one std::type_info is a sub/super-type or another std::type_info.
There's no portable way to do it without explicitly registering base/derived relationships. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:ulkvkzpdi.fsf@boost-consulting.com...
"Korcan Hussein" <korcan_h@hotmail.com> writes:
So does anybody know of a good method to determine if one std::type_info is a sub/super-type or another std::type_info.
There's no portable way to do it without explicitly registering base/derived relationships.
I thought as much, worth a try though ;-) while i'm pondering ideas i'm open to any suggestions people may have :)
participants (6)
-
David Abrahams
-
Fred Bertsch
-
Joaquín Mª López Muñoz
-
Joel de Guzman
-
Korcan Hussein
-
Pavel Vozenilek