Re:RE: [boost] Re: FORMAL Review of "Output Formatter" library -

Robert Ramey wrote:
Although my library is still under review, I am re-architecturing it based on the feedback thus far. This post is the code associated with what was the delimiters/formatters part of the library. They are now given the better name of "decorators".
If your making changes in the library already, maybe you might want to consider withdrawing it from the formal review and re-submitting it after you've made all the changes you want to make. It might be easier (for you as well as for reviewers) than going through the whole process more than once.
IIUC, the serialization library went through several reviews before being accepted. This is the best place to get decent feedback on a library from the most people. If I withdraw the library, there may be a comment that I miss (because the reviewer has not posted it since the library is withdrawn) that makes an important point. I have had lots of feedback regarding the names of the various components. The changes I have made are an attempt to pre-emptively address these issues and to say that I am taking all the comments into consideration. Regards, Reece _________________________________________________________________ Use MSN Messenger to send music and pics to your friends http://www.msn.co.uk/messenger

I've been working on a multimethod library for C++ and, in my opinion, it's turned out rather well. It's modeled closely after the multimethods in CLOS and Dylan so it's more flexible than the other (pure C++) multimethod libraries I have seen. In particular, new methods can be added at runtime, polymorphic dispatch doesn't require exact matches, and methods can call the next most specific method (sort of how a virtual member can call the inherited member). The nicest feature of multimethods is that they allow classes to be extended with virtual members without editing the classes. It's completely transparent: the class doesn't need to be coded to allow for multimethods and new multimethods can be added without touching any existing code. It's a far nicer model than using the Visitor pattern. The other advantage is that it makes multiple dispatch trivial. This is useful for things like intersection tests, drag and drop, event + view message handling, etc. Without multiple dispatch these sorts of things are rather painful to write and normally require a lot of switching on types. The design is quite simple: there's a generic function object to which you dynamically add compatible function objects (using operator<<), an operator() that is invoked which will then call the most specialized function object (or method) that applies to the actual arguments, and a next_method member that can be used within a method to call the next most specialized method. The source can be found at <http://sourceforge.net/projects/multimethods/>. Currently it works with CodeWarrior 9.2. There are a bunch of test files, but no examples or docs as of yet. So, does this sound like something boost would be interested in? -- Jesse

Jesse Jones <jesjones@mindspring.com> writes:
I've been working on a multimethod library for C++ and, in my opinion, it's turned out rather well. It's modeled closely after the multimethods in CLOS and Dylan so it's more flexible than the other (pure C++) multimethod libraries I have seen. In particular, new methods can be added at runtime, polymorphic dispatch doesn't require exact matches, and methods can call the next most specific method (sort of how a virtual member can call the inherited member).
The nicest feature of multimethods is that they allow classes to be extended with virtual members without editing the classes. It's completely transparent: the class doesn't need to be coded to allow for multimethods and new multimethods can be added without touching any existing code. It's a far nicer model than using the Visitor pattern.
The other advantage is that it makes multiple dispatch trivial. This is useful for things like intersection tests, drag and drop, event + view message handling, etc. Without multiple dispatch these sorts of things are rather painful to write and normally require a lot of switching on types.
The design is quite simple: there's a generic function object to which you dynamically add compatible function objects (using operator<<), an operator() that is invoked which will then call the most specialized function object (or method) that applies to the actual arguments, and a next_method member that can be used within a method to call the next most specialized method.
The source can be found at <http://sourceforge.net/projects/multimethods/>. Currently it works with CodeWarrior 9.2. There are a bunch of test files, but no examples or docs as of yet.
So, does this sound like something boost would be interested in?
How does this stack up against http://tinyurl.com/5qxky? -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

On Sep 18, 2004, at 4:15 AM, David Abrahams wrote:
How does this stack up against http://tinyurl.com/5qxky?
Here's a rundown on my impression of Danil's library. (-) are points where I think my library is better, (+) where Danil's library is better: - Danil uses type lists to do dispatch. In other words, like most C++ multimethod libs, it's a purely compile time solution. This has some advantages, but has the major disadvantage that the methods are fixed at compile time. This makes it a lot more difficult to use multimethods in any sort of reusable framework. - There's no support for any kind of next_method feature. This is really important for some applications (think of event + view dispatching for example). Users might be able to manually call the appropriate next method, but that seems like a brittle and error-prone solution. - Danil's solution is intrusive: it requires that classes that are dispatched upon have an Accept member and members for each operation that you want to treat as a multimethod. This is really bad IMO (altho not all type list solutions impose this requirement). - It's a minor point, but Danil syntactically distinguishes the first argument. For example, to test if two shapes intersect he uses code like this: arg0->Cross(arg1). This is a bit goofy: the whole point of multimethods is that none of the arguments are distinguished and that operations do not belong to objects (and are therefore readily extensible). - His example has some gnarly template code at the user level. I doubt many users are going to want to build type lists by hand using compile-time ifs. It's also not going to scale very well past two arguments if people have to write that stuff by hand. + Danil's code will dispatch faster. Mainly because he moves more logic into compile time and doesn't support next_method. + All of his code is header level stuff. I have one cpp file. + He's able to use compile time tests for subtyping. I have to do this at runtime so types that are to be polymorphically dispatched must inform the system of their base class(es) using a macro like this: DECLARE_SUBTYPE(line_shape, shape);. + Symmetric methods are easier with his scheme (eg circle + rect and rect + circle can be implemented with one method). -- Jesse

Jesse Jones <jesjones@mindspring.com> writes:
On Sep 18, 2004, at 4:15 AM, David Abrahams wrote:
How does this stack up against http://tinyurl.com/5qxky?
Here's a rundown on my impression of Danil's library. (-) are points where I think my library is better, (+) where Danil's library is better:
Okay, for the record, I'm interested in your library. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

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. 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. 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. There might still be issues with dynamically unloading templated code though. 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 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 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 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 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) 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 12) decent dispatch time (= has never showed up in any profiling we've done) 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. Documentation: http://seal.web.cern.ch/seal/snapshot/apiref/ classseal_1_1MultiMethod.html API and implementation: http://lcgapp.cern.ch/lxr/SEAL/source/Foundation/SealBase/SealBase/ MultiMethod.h http://lcgapp.cern.ch/lxr/SEAL/source/Foundation/SealBase/src/ MultiMethod.cpp Tests: http://lcgapp.cern.ch/lxr/SEAL/source/Foundation/SealBase/tests/ MultiMethod01.cpp http://lcgapp.cern.ch/lxr/SEAL/source/Foundation/SealBase/tests/ MultiMethod02.cpp http://lcgapp.cern.ch/lxr/SEAL/source/Foundation/SealBase/tests/ MultiMethod03.cpp Depends on: http://lcgapp.cern.ch/lxr/SEAL/source/Foundation/SealBase/SealBase/ XTypeInfo.h http://lcgapp.cern.ch/lxr/SEAL/source/Foundation/SealBase/src/ XTypeInfo.cpp Non-test examples of use: http://lxcms73.cern.ch/lxr/IGUANACMS/ident?i=MMM_DEFUN_FUNC Lassi -- If you think nobody cares, try missing a couple of payments.

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

On Sat, 18 Sep 2004 07:15:10 -0400, David Abrahams wrote: I am currently using Jesse's multimethods in a project of mine, and I should state up front they work very well from my own usage of them. I've also been helping him getting them to compile properly on Linux/GCC (3.3.x and 3.4.x).
How does this stack up against http://tinyurl.com/5qxky? I did not know about this before using Jesse's multimethods - though I have to agree with Jesse, that requiring the end-user to implement some function or another is not appealing. But then, I looked at the above URL, and found it difficult to follow, mainly because the example is mixed in with the rest of the code, making it very difficult to follow, or use in a generic way without going through it with a fine tooth comb to decipher it.
As for a speed comparison, etc. I cannot say, however Jesse's implementation is quite fast enough for my needs. Jesse probably needs to do some more work to allow more than two arguments to the functions used in his multimethods, and to allow it to skip the lookup code for parameters that are rigidly defined (ie. non-polymorphic), however, from an end-users point of view, his code IS quite easy to implement and use. I would love to see Jesse's code make it into boost - though, I would also like to see a version of the multimethods implementation in the URL you pasted that is not inter-mingled with a specific example (ie. the implementation of the feature, and the example in separate files) as well, especially if the requirement for implementing a specific function can be bypassed. This kind of functionality greatly interests me :) -- PreZ Founder The Neuromancy Society http://www.neuromancy.net

Jesse Jones <jesjones@mindspring.com> writes:
The source can be found at <http://sourceforge.net/projects/multimethods/>. Currently it works with CodeWarrior 9.2. There are a bunch of test files, but no examples or docs as of yet.
AFAICS nothing has been committed to the CVS. Is there really anything there at all? -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

On Sep 18, 2004, at 4:17 AM, David Abrahams wrote:
Jesse Jones <jesjones@mindspring.com> writes:
The source can be found at <http://sourceforge.net/projects/multimethods/>. Currently it works with CodeWarrior 9.2. There are a bunch of test files, but no examples or docs as of yet.
AFAICS nothing has been committed to the CVS. Is there really anything there at all?
Yes. :-) SourceForge's commit stats have been flaky for years now. And I've noticed problems lately with trying to do online CVS browsing for several projects. I'll post the code to the vault later today. -- Jesse

On Sep 18, 2004, at 4:17 AM, David Abrahams wrote:
Jesse Jones <jesjones@mindspring.com> writes:
The source can be found at <http://sourceforge.net/projects/multimethods/>. Currently it works with CodeWarrior 9.2. There are a bunch of test files, but no examples or docs as of yet.
AFAICS nothing has been committed to the CVS. Is there really anything there at all?
The vault was full so I released the source on SourceForge. You can download it at: <https://sourceforge.net/projects/multimethods/>. -- Jesse
participants (6)
-
Daniel Wallin
-
David Abrahams
-
Jesse Jones
-
Lassi A.Tuura
-
Preston A. Elder
-
Reece Dunn