Boost.MPI accepted

It is my pleasure to announce that Boost.MPI has been accepted as a Boost library. Congratulations to Doug Gregor and Matthias Troyer on their excellent contribution to Boost! One particularly nice aspect of Boost.MPI is the way it leverages the Boost serialization library. So also thanks to the author of that library, Robert Ramey. Yeah generic programming and code reuse! I would also like to thank all of the people that took some time to review Boost.MPI and participate in the review discussion: Dean Michael Berris, Robert Ramey, David Abrahams, Geoffrey Irving, John Fletcher, John Phillips, and Noel Belcourt. During the review, several suggestions for improvement were made, which I recommend that the authors take action on as they prepare Boost.MPI to be included in Boost. 1. Named parameters in the interface 2. Revise introduction to focus more on describing what Boost.MPI is, and move info about how Boost.MPI is implemented to a later section. 3. Document the performance characteristics of functions, e.g., Create_vector. 4. A copy-edit pass over the docs to catch typos, etc. 5. Hooks for dispatching between the underlying MPI implementation vs. a Boost.MPI provided impl. Cheers, Jeremy __________________________________ Jeremy Siek <siek@cs.colorado.edu> http://www.cs.colorado.edu/~siek/ Visiting Assistant Professor Department of Computer Science University of Colorado at Boulder

One more point... On Sep 21, 2006, at 7:02 AM, Jeremy Siek wrote:
1. Named parameters in the interface 2. Revise introduction to focus more on describing what Boost.MPI is, and move info about how Boost.MPI is implemented to a later section. 3. Document the performance characteristics of functions, e.g., Create_vector. 4. A copy-edit pass over the docs to catch typos, etc. 5. Hooks for dispatching between the underlying MPI implementation vs. a Boost.MPI provided impl.
6. In most cases, but not all, the requirements on type parameters are documented. Make sure to double checked that they are documented in all cases. Also, it would be easier to find these requirements if they were given a subsubsection with the title "Type Requirements" for each item in the docs, just as is done in the SGI STL docs. -Jeremy P.S. I originally missed several of the review emails due to changes in the subject line. However, I've found them all now. __________________________________ Jeremy Siek <siek@cs.colorado.edu> http://www.cs.colorado.edu/~siek/ Visiting Assistant Professor Department of Computer Science University of Colorado at Boulder

Jeremy Siek wrote:
[suggestions] 1. Named parameters in the interface
One tiny observaton. The suggestion of named parameters for the interface could well be applied to many if not most if not all libraries. Could this not be considered as a separate orthogonal layer to the current interface? This would a) make the named parameter interface available where convenient b) make it optional rather than obligatory c) set the precedent for other libraries which might benefit from a named parameter interface - without the need to re-do any of the library itself. Perhaps there could even be a convention such as boost/named_parameters/date_time.hpp ... or perhaps boost/date_time/named_parameters.hpp Robert Ramey

"Robert Ramey" <ramey@rrsd.com> writes:
Jeremy Siek wrote:
[suggestions] 1. Named parameters in the interface
One tiny observaton. The suggestion of named parameters for the interface could well be applied to many if not most if not all libraries.
I doubt the suggestion can be made as convincingly in most cases. It makes sense where you have many functions with either: a. many parameters with the "same" type (e.g. all integral), so you really want to distinguish them by name because the typechecker won't prevent you from getting the order wrong b. many parameters with useful defaults and no linear ordering dependency among them. In other cases, it provides less benefit.
Could this not be considered as a separate orthogonal layer to the current interface? This would
a) make the named parameter interface available where convenient
OK, good idea.
b) make it optional rather than obligatory
I don't understand; It's already optional.
c) set the precedent for other libraries which might benefit from a named parameter interface - without the need to re-do any of the library itself.
You don't need to "re-do the library." It's a trivial transformation to add a named parameter interface to an existing function. Just rename it slightly or put it in a detail namespace and dispatch to it from the named-parameter-enabled function that uses the implementation function's original name. To clients of the original function, there's practically no detectable difference.
Perhaps there could even be a convention such as
boost/named_parameters/date_time.hpp ...
or perhaps
boost/date_time/named_parameters.hpp
I understand why we want to do that for, e.g., Python bindings. Having Python installed and linking with it is a responsibility nobody wants to accept unless they need Python. Using Boost.Parameter is not the same sort of thing; it comes with Boost and is transparent to build/configuration issues. I'm not saying what you're suggesting is a bad idea; I just don't see what great advantage it offers. -- Dave Abrahams Boost Consulting www.boost-consulting.com

On 9/22/06, David Abrahams <dave@boost-consulting.com> wrote:
[snipped]
Using Boost.Parameter is not the same sort of thing; it comes with Boost and is transparent to build/configuration issues. I'm not saying what you're suggesting is a bad idea; I just don't see what great advantage it offers.
Faster compile time? Boost.Parameter uses a great deal of metaprogramming, and I used a little here in a project of mine. It really makes the interface better, but the compile times grow a lot. IMO, they are worth, but I doubt everybody would agree.
-- Dave Abrahams Boost Consulting www.boost-consulting.com
-- Felipe Magno de Almeida

"Felipe Magno de Almeida" <felipe.m.almeida@gmail.com> writes:
On 9/22/06, David Abrahams <dave@boost-consulting.com> wrote:
[snipped]
Using Boost.Parameter is not the same sort of thing; it comes with Boost and is transparent to build/configuration issues. I'm not saying what you're suggesting is a bad idea; I just don't see what great advantage it offers.
Faster compile time? Boost.Parameter uses a great deal of metaprogramming, and I used a little here in a project of mine. It really makes the interface better, but the compile times grow a lot.
Really? By how much? and on what compiler? I would very much appreciate seeing numbers. Are you using the latest Boost.Parameter macros to enable your functions, or are you making lots of use of the old idioms? Extensive use of binding<>, especially, is likely to make it expensive at compile-time.
IMO, they are worth, but I doubt everybody would agree.
Let's have some numbers; if they are very bad I'll be convinced (but also highly motivated to optimize the library). -- Dave Abrahams Boost Consulting www.boost-consulting.com

On 9/22/06, David Abrahams <dave@boost-consulting.com> wrote:
"Felipe Magno de Almeida" <felipe.m.almeida@gmail.com> writes:
On 9/22/06, David Abrahams <dave@boost-consulting.com> wrote:
[snipped]
Using Boost.Parameter is not the same sort of thing; it comes with Boost and is transparent to build/configuration issues. I'm not saying what you're suggesting is a bad idea; I just don't see what great advantage it offers.
Faster compile time? Boost.Parameter uses a great deal of metaprogramming, and I used a little here in a project of mine. It really makes the interface better, but the compile times grow a lot.
Really? By how much? and on what compiler? I would very much appreciate seeing numbers.
Are you using the latest Boost.Parameter macros to enable your functions, or are you making lots of use of the old idioms? Extensive use of binding<>, especially, is likely to make it expensive at compile-time.
Oh, there were changes? No, no, I dont think I was using any macros. But I was using only named templated parameters. I really dont know how it compares.
IMO, they are worth, but I doubt everybody would agree.
Let's have some numbers; if they are very bad I'll be convinced (but also highly motivated to optimize the library).
I dont have hard data. But a three classes library, using only named template parameters (four each) and instantiated three times was taking roughly 30 seconds to compile. VC7.1 on a AMD 64 X2 3800+
-- Dave Abrahams Boost Consulting www.boost-consulting.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- Felipe Magno de Almeida

"Felipe Magno de Almeida" <felipe.m.almeida@gmail.com> writes:
On 9/22/06, David Abrahams <dave@boost-consulting.com> wrote:
Are you using the latest Boost.Parameter macros to enable your functions, or are you making lots of use of the old idioms? Extensive use of binding<>, especially, is likely to make it expensive at compile-time.
Oh, there were changes?
Lots.
No, no, I dont think I was using any macros. But I was using only named templated parameters. I really dont know how it compares.
IMO, they are worth, but I doubt everybody would agree.
Let's have some numbers; if they are very bad I'll be convinced (but also highly motivated to optimize the library).
I dont have hard data. But a three classes library, using only named template parameters (four each) and instantiated three times was taking roughly 30 seconds to compile. VC7.1 on a AMD 64 X2 3800+
That means nothing until we know how much of that time was due to the use of the parameter library. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Robert Ramey" <ramey@rrsd.com> writes:
b) make it optional rather than obligatory
I don't understand; It's already optional.
c) set the precedent for other libraries which might benefit from a named parameter interface - without the need to
You don't need to "re-do the library." It's a trivial transformation to add a named parameter interface to an existing function. Just rename it slightly or put it in a detail namespace and dispatch to it from the named-parameter-enabled function that uses the implementation function's original name. To clients of the original function, there's practically no detectable difference.
OK - I understood that the suggestion was to replace the public interface with a parameter based one. So, once it is characterised as an optional add-on then it raises the question as to why the same idea shouldn't be more widely applied. That is what I meant. Robert Ramey

"Robert Ramey" <ramey@rrsd.com> writes:
David Abrahams wrote:
"Robert Ramey" <ramey@rrsd.com> writes:
b) make it optional rather than obligatory
I don't understand; It's already optional.
c) set the precedent for other libraries which might benefit from a named parameter interface - without the need to
You don't need to "re-do the library." It's a trivial transformation to add a named parameter interface to an existing function. Just rename it slightly or put it in a detail namespace and dispatch to it from the named-parameter-enabled function that uses the implementation function's original name. To clients of the original function, there's practically no detectable difference.
OK - I understood that the suggestion was to replace the public interface with a parameter based one.
Yes it was.
So, once it is characterised as an optional add-on then it raises the question as to why the same idea shouldn't be more widely applied.
Yes, a reasonable question, to be sure. -- Dave Abrahams Boost Consulting www.boost-consulting.com

Robert Ramey wrote:
Jeremy Siek wrote:
[suggestions] 1. Named parameters in the interface
One tiny observaton. The suggestion of named parameters for the interface could well be applied to many if not most if not all libraries. Could this not be considered as a separate orthogonal layer to the current interface? This would
a) make the named parameter interface available where convenient b) make it optional rather than obligatory c) set the precedent for other libraries which might benefit from a named parameter interface - without the need to re-do any of the library itself.
Perhaps there could even be a convention such as
boost/named_parameters/date_time.hpp ...
or perhaps
boost/date_time/named_parameters.hpp
Robert Ramey
I didn't follow the original discussion, just read David's and your's suggestions to solve "foo(int, int)" problem. And I'm in favor of your solution. If I understand it correctly, the choice is between solution 1 (David): foo(param1 = val1, param2 = val2); foo(param2 = val2, param1 = val1); and solution 2 (Robert or me if I've forgot your original idea): foo(param1_type(val1), param2_type(val2)); foo(param2_type(val2), param1_type(val1)); // NOTE: it can also be used like that param1_type p1(val1); // it can be defined in one place and used in many places param2_type p2(val2); foo(p1, p2); // It can be used in many places to reduce code bloat foo(p2, p1); // Can it be achieved with first solution? it assumes that there are strong typedefs (or Beman Davis's identifiers) for param1_type and param2_type I'm for the second solution. Anyway, as I remember from D&E book there was a proposal to add named params to the language, but it was rejected because of named params encourage procedure-style programming and C++ was positionad as a OO language. Of course, now it is positioned as a multiparadigm language, but priorities remain the same: OO is preferred over procedural in C++. or may be I'm missing something? In OO there is no reason to have naked integers that represents different logical entities. It is alway sensible to use strong type checking by making it a different types (strong typedef or identifier, or by hand) but named params are orthogonal to naked-wrapped problem it is just a syntactic sugar over already strongly typed entities. So, I'm second to Robert Ramey in "make it optional rather than obligatory" statement. But the best solution for me is - "just forget about named params" reason: consider the introductory example from boost::parameter lib: new_window("alert", width=10, titlebar=false); if I'll see such a line in a real code, my first idea would be - "there are variables width and titlebar somewhere around and this line assigns new values to them and calls a function new_window with corresponding parameters". Of course it is completely wrong. Conclusion - I'll never use this library for code that should be maintained in a long term. Note: this code compiles perfectly: void new_window(char const* const, int, bool); int main() { int width; bool titlebar; new_window("alert", width=10, titlebar=false); return 0; } The second introductory example: //-------------------------------------------------------------- Since an argument's meaning is given by its position, we have to choose an (often arbitrary) order for parameters with default values, making some combinations of defaults unusable: window* new_window( char const* name, int border_width = default_border_width, bool movable = true, bool initially_visible = true ); const bool movability = false; window* w = new_window("alert box", movability); In the example above we wanted to make an unmoveable window with a default border_width, but instead we got a moveable window with a border_width of zero. To get the desired effect, we'd need to write: window* w = new_window( "alert box", default_border_width, movability); It can become difficult for readers to understand the meaning of arguments at the call site: window* w = new_window("alert", 1, true, false); Is this window moveable and initially invisible, or unmoveable and initially visible? The reader needs to remember the order of arguments to be sure. The author of the call may not remember the order of the arguments either, leading to hard-to-find bugs. This library addresses the problems outlined above by associating each parameter with a keyword object. Now users can identify arguments by keyword, rather than by position: window* w = new_window("alert box", movable=false); // OK! //-------------------------------------------------------------- Sounds reasonable, but note drawback mentioned above. There is an alternative solution for all problems mentioned in this example: struct TWindowCreationParams { TWindowCreationParams() : border_width(default_border_width), movable(true), initially_visible(true) {} int border_width; bool movable; bool initially_visible; }; window* new_window( char const* name, TWindowCreationParams const& params ); usage becomes: TWindowCreationParams aParams; aParams.movable = false; window* w = new_window("alert box", aParams); // was: // window* w = new_window("alert box", movable=false); // // window* w = new_window("alert", 1, true, false); // becomes: // TWindowCreationParams aParams; aParams.border_width = 1; aParams.initially_visible = false; window* w = new_window("alert box", aParams); // with parameter lib it would be: // window* w = new_window("alert box", border_width = 1, initially_visible=false); The solution with auxiliary structure for parameter bundling is just slightly more verbose, but 1) it is exact (it is hard to interpret in a wrong way) 2) it doesn't pollute namespace with parameter names 3) instance of params structure can be reused many times reducing code duplication/bloating. Sorry for so long opus, but I really wonder why David Abrahams and Daniel Wallin put so great effort in the parameter lib. I can not see it's advantages. Oleg Abrosimov.

On 9/23/06, Oleg Abrosimov <beholder@gorodok.net> wrote:
The solution with auxiliary structure for parameter bundling is just slightly more verbose, but 1) it is exact (it is hard to interpret in a wrong way) 2) it doesn't pollute namespace with parameter names 3) instance of params structure can be reused many times reducing code duplication/bloating.
Sorry for so long opus, but I really wonder why David Abrahams and Daniel Wallin put so great effort in the parameter lib. I can not see it's advantages.
Problems with your approach include: a) parameter values are copied b) parameter values need to be default-constructable (into a valid state) c) you cannot check whether mandatory parameters are supplied at compile-time (I believe) Regards, Michael

Michael Walter wrote:
On 9/23/06, Oleg Abrosimov <beholder@gorodok.net> wrote:
Anyway, as I remember from D&E book there was a proposal to add named params to the language, but it was rejected because of named params encourage procedure-style programming and C++ was positionad as a OO language. Of course, now it is positioned as a multiparadigm language, but priorities remain the same: OO is preferred over procedural in C++. or may be I'm missing something?
The entire STL is about as far from OO as one can imagine, so I'd say so. Smalltalk supports positional parameters and it's about as 'pure OO' as you can get.
The solution with auxiliary structure for parameter bundling is just slightly more verbose, but 1) it is exact (it is hard to interpret in a wrong way) 2) it doesn't pollute namespace with parameter names 3) instance of params structure can be reused many times reducing code duplication/bloating.
Sorry for so long opus, but I really wonder why David Abrahams and Daniel Wallin put so great effort in the parameter lib. I can not see it's advantages.
Problems with your approach include:
a) parameter values are copied b) parameter values need to be default-constructable (into a valid state) c) you cannot check whether mandatory parameters are supplied at compile-time (I believe)
I'll put it another way. As software complexity has increased the number of options one might need to configure a particular class or function can become quite large. Most of these options will typically have appropriate default values and hence won't need to be user specified. However, making a set of overloads with positional parameters in combinations that make sense may be difficult or impossible. Sure, you can make intermediate types, but really that's just a bit of noise that detracts from the users purpose. Named parameters provide for code clarity where positional parameters cannot. As an example, in date-time with the formatting facets there's all sorts of strings (month names, week names, infinity names) and other options that the user might want to override the defaults. Typically a user wouldn't override all of these, just a few. Currently the library doesn't provide constructors that allow the user to override the options on construction -- it's just not reasonable with positional parameters and overloading. Rather, they have to construct and then modify. This is, in my view inferior -- I'd rather have an immutable facet type which handles all the overrides at time of construction. This is enough of an issue that other languages have seen fit to incorporate this directly into the language -- Ada, Smalltalk, Objective-C to name a few. In other languages this is a proposed feature http://dev.perl.org/perl6/rfc/57.html http://www.mozilla.org/js/language/es4/rationale/named.html In the meantime, perl 5 coders use conventions with hash data structures to accomplish what the perl 6 language feature would do. It's an extremely common idiom in perl code. Ruby, Python and other 'hot' languages all have ways to do this as well. I, for one, am happy they have made the effort to provide a common way to do this in C++. It's even more amazing to me that their's virtually no loss of efficiency. It's only thru this sort of experimentation and effort that programming practices can be improved. I'd eventually like to see a language feature, but that's a different discussion.... Jeff

Jeff Garland <jeff@crystalclearsoftware.com> writes:
I, for one, am happy they have made the effort to provide a common way to do this in C++. It's even more amazing to me that their's virtually no loss of efficiency.
Not virtually. According to the best measurements we have, there's just plain no loss of efficiency. If you believe the numbers, there might even be an efficiency gain.
It's only thru this sort of experimentation and effort that programming practices can be improved. I'd eventually like to see a language feature, but that's a different discussion....
Quite so. -- Dave Abrahams Boost Consulting www.boost-consulting.com

Hello David, As a result of this discussion I've read boost::parameter docs completely. And now I want to apologize for my aggressive post. This library is very sophisticated. Nevertheless, I didn't become it's proponent and there are some thoughts about the overall function parameters problem that can be useful for this discussion: 1) parameter's type is not a panacea It means that giving function parameters unique types can solve the problem of mistakenly swapping them, but is not always applicable, sometimes impractical, doesn't solve problem with optional parameters, etc. 2) many parameters: - some are mandatory and - some are optional with default values supplied It means that both optional and required parameters should be taken into account. Definition: configuration - is a set of parameters for a given function f1(configuration); Requirements for ideal solution of implementing and using function's configurations: 1) simple implementation of configuration and function that uses it 2) maximum maintainability it means: a) configuration parameters should be specified as close to function call as possible b) configuration parameters should be visible (names) c) configuration reuse solutions: 1) positional function parameters + mandatory parameters + optional parameters - invisible parameters - interference of optional parameters complicates its usage - reuse is not possible + no ambiguity with other language constructs + implementation is simple 2) named parameters + mandatory parameters + optional parameters + visible parameters - reuse is not possible (it is not _very_ important, but important. Is there a way to extend parameter lib to support such a reuse?) - ambiguity with other language constructs (it is very important drawback. As I realized from parameter docs, great effort should be made to make such an ambiguity possible. It would be better IMO to eliminate this efforts in implementation and the ambiguity in one shot - provide special may be auxiliary structure - like syntax to use parameters) - implementation is not simple (really. all this nightmare can be done for library that is created once and used many times, but I need a tool that can be used on a daily basis for ordinary code. it means that simplicity of an implementation should be very close to the solution with auxiliary structures below) 3) auxiliary structures - mandatory parameters + optional parameters + visible parameters + reuse is possible + no ambiguity with other language constructs + implementation is simple The last approach with auxiliary structures has only one drawback - it is not possible to have required parameters with it. May be you, David, can see a way how parameter lib can be reused/extended into something like the las solution, but with all '+' marks? ( I remember additional arguments by Michael Walter: a) parameter values are copied b) parameter values need to be default-constructable (into a valid state) but they are not important for me just now ) May be the best solution that we can have now is: //implementation: BOOST_PARAM_STRUCT_BEGIN(TFuncParams) BOOST_DECLARE_PARAM_OPTIONAL(type1, name1, def_val1) BOOST_DECLARE_PARAM_REQIRED(type2, name2) BOOST_DECLARE_PARAM_OPTIONAL(type3, name3, def_val3) BOOST_DECLARE_PARAM_OPTIONAL(type4, name4, def_val4) BOOST_PARAM_STRUCT_END() void func(TFuncParams const& params) { cout << params.name1; // etc. } usage: BOOST_INSTANCIATE_PARAM_STRUCT_BEGIN(TFuncParams, params) BOOST_PARAM_OPTIONAL(params, name1, val1) BOOST_PARAM_REQIRED(params, name2, val2) BOOST_INSTANCIATE_PARAM_STRUCT_END() func(params); The idea is that all boost::parameter magic is hidden by those macroses. The question is - can it be really done? Oleg Abrosimov.

Oleg Abrosimov <beholder@gorodok.net> writes:
Hello David,
As a result of this discussion I've read boost::parameter docs completely. And now I want to apologize for my aggressive post. This library is very sophisticated. Nevertheless, I didn't become it's proponent and there are some thoughts about the overall function parameters problem that can be useful for this discussion:
1) parameter's type is not a panacea
It means that giving function parameters unique types can solve the problem of mistakenly swapping them, but is not always applicable, sometimes impractical,
If you're referring to deduced parameters (http://tinyurl.com/mayug#deduced-function-parameters), of course it's not a panacea. That's why the library supports named parameters.
doesn't solve problem with optional parameters, etc.
I don't know what problem you're referring to, but deduced parameters, where applicable, certainly do solve the main problem with optional parameters (spurious order dependencies).
2) many parameters: - some are mandatory and - some are optional with default values supplied
It means that both optional and required parameters should be taken into account.
Both optional and required parameters are taken into account by the Parameter library. What documentation did you read that made you think they weren't?
Definition: configuration - is a set of parameters for a given function f1(configuration);
Requirements for ideal solution of implementing and using function's configurations: 1) simple implementation of configuration and function that uses it 2) maximum maintainability it means: a) configuration parameters should be specified as close to function call as possible b) configuration parameters should be visible (names) c) configuration reuse
solutions: 1) positional function parameters + mandatory parameters + optional parameters - invisible parameters
??
- interference of optional parameters complicates its usage - reuse is not possible + no ambiguity with other language constructs + implementation is simple
2) named parameters + mandatory parameters + optional parameters + visible parameters - reuse is not possible (it is not _very_ important, but important. Is there a way to extend parameter lib to support such a reuse?)
You're not saying what you mean by "reuse." We think reuse is very possible with the Parameter library, so it's quite unclear what you might be referring to.
- ambiguity with other language constructs (it is very important drawback. As I realized from parameter docs,
You're not being specific enough here either. I can't imagine what ambiguity you mean.
great effort should be made to make such an ambiguity possible. It would be better IMO to eliminate this efforts in implementation and the ambiguity in one shot - provide special may be auxiliary structure - like syntax to use parameters)
It's unclear what you mean.
- implementation is not simple (really. all this nightmare can be done for library that is created once and used many times, but I need a tool that can be used on a daily basis for ordinary code.
One can use Boost.Parameter for ordinary code on a daily basis. We (Boost Consulting) have done it for our major customers and they are *very* satisfied with the results.
it means that simplicity of an implementation should be very close to the solution with auxiliary structures below)
IMO the implementation complexity doesn't matter as long as it works and gives comprehensible feedback when misused. Do you inspect the source code of your compiler and complain about its implementation complexity?
3) auxiliary structures - mandatory parameters + optional parameters + visible parameters + reuse is possible + no ambiguity with other language constructs + implementation is simple
The last approach with auxiliary structures has only one drawback - it is not possible to have required parameters with it. May be you, David, can see a way how parameter lib can be reused/extended into something like the las solution, but with all '+' marks?
No, and it has more drawbacks. Go back and read the Parameter library review commentary if you want to find all of them.
( I remember additional arguments by Michael Walter:
a) parameter values are copied b) parameter values need to be default-constructable (into a valid state)
but they are not important for me just now )
Well, those are two of the drawbacks, and they count (maybe not for you, but they do count).
May be the best solution that we can have now is:
//implementation: BOOST_PARAM_STRUCT_BEGIN(TFuncParams) BOOST_DECLARE_PARAM_OPTIONAL(type1, name1, def_val1) BOOST_DECLARE_PARAM_REQIRED(type2, name2) BOOST_DECLARE_PARAM_OPTIONAL(type3, name3, def_val3) BOOST_DECLARE_PARAM_OPTIONAL(type4, name4, def_val4) BOOST_PARAM_STRUCT_END()
That's not a nightmare?
void func(TFuncParams const& params) { cout << params.name1; // etc. }
usage: BOOST_INSTANCIATE_PARAM_STRUCT_BEGIN(TFuncParams, params) BOOST_PARAM_OPTIONAL(params, name1, val1) BOOST_PARAM_REQIRED(params, name2, val2) BOOST_INSTANCIATE_PARAM_STRUCT_END()
func(params);
The idea is that all boost::parameter magic is hidden by those macroses. The question is - can it be really done?
I don't know. The above meets few if any of my requirements for such a library, so determining feasibility will have to fall to someone else. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams writes:
Oleg Abrosimov <beholder@gorodok.net> writes:
Hello David,
As a result of this discussion I've read boost::parameter docs completely. And now I want to apologize for my aggressive post. This library is very sophisticated. Nevertheless, I didn't become it's proponent and there are some thoughts about the overall function parameters problem that can be useful for this discussion:
1) parameter's type is not a panacea
It means that giving function parameters unique types can solve the problem of mistakenly swapping them, but is not always applicable, sometimes impractical,
If you're referring to deduced parameters (http://tinyurl.com/mayug#deduced-function-parameters), of course it's not a panacea. That's why the library supports named parameters.
Yes, it is exactly what I mean.
doesn't solve problem with optional parameters, etc.
I don't know what problem you're referring to, but deduced parameters, where applicable, certainly do solve the main problem with optional parameters (spurious order dependencies).
Yes, but note the "where applicable" constrain. When I speak "doesn't solve" I mean that it can not be used to solve the problem in all cases, only "where applicable".
2) many parameters: - some are mandatory and - some are optional with default values supplied
It means that both optional and required parameters should be taken into account.
Both optional and required parameters are taken into account by the Parameter library. What documentation did you read that made you think they weren't?
You are excited a bit, dissipate your energy, please. Here I'm formulating my requirements for parameter lib that would be good for me. Of course boost::parameter support it!
Definition: configuration - is a set of parameters for a given function f1(configuration);
Requirements for ideal solution of implementing and using function's configurations: 1) simple implementation of configuration and function that uses it 2) maximum maintainability it means: a) configuration parameters should be specified as close to function call as possible b) configuration parameters should be visible (names) c) configuration reuse
solutions: 1) positional function parameters + mandatory parameters + optional parameters - invisible parameters
??
consider foo(1, 2); // reader have no glue about what parameters mean // I call it invisible parameters foo(width = 2, height = 1); // boost::parameter - visible
- interference of optional parameters complicates its usage - reuse is not possible + no ambiguity with other language constructs + implementation is simple
2) named parameters + mandatory parameters + optional parameters + visible parameters - reuse is not possible (it is not _very_ important, but important. Is there a way to extend parameter lib to support such a reuse?)
You're not saying what you mean by "reuse." We think reuse is very possible with the Parameter library, so it's quite unclear what you might be referring to.
libraries are all about reuse. boost::parameter is not an exception of course. By reuse I mean configuration reuse in client code. Not reuse of boost::parameter library in other libs. Consider: foo(width = 2, height = 1); // ... some code ... foo(width = 2, height = 3); vs. TFooParam p; p.width = 2; p.height = 1; foo(p); // ... some code ... p.height = 3; foo(p); // p is reused here The drawback in such a scenario is reduced visibility, because of 'p' can be initialized too far from the second call of 'foo'. But in practice most common scenario is to initialize 'p', call 'foo(p)', then modify 'p' slightly and call 'foo(p)' again. It means that visibility is preserved.
- ambiguity with other language constructs (it is very important drawback. As I realized from parameter docs,
You're not being specific enough here either. I can't imagine what ambiguity you mean.
consider: void new_window(char const* const, int = 10, bool = true); int main() { int width; bool titlebar; new_window("alert", width=10, titlebar=false); return 0; } call to new_window can not be translated unambiguously by reader in presence of named params. I expect that compiler will complain, but reader can be fooled by such a call, especially if we change it a bit: int main() { new_window("alert", width=10, titlebar=false); return 0; } What is a 'width' here? parameter name? or some variable in global scope?
great effort should be made to make such an ambiguity possible. It would be better IMO to eliminate this efforts in implementation and the ambiguity in one shot - provide special may be auxiliary structure - like syntax to use parameters)
It's unclear what you mean.
I mean that significant amount of work should be done to allow named parameter syntax that can be ambiguous as was shown above. The idea I was trying to explain is simple - May be it is possible to find a way to achieve both goals - unambiguity and reduce of efforts required to enable named params usage.
- implementation is not simple (really. all this nightmare can be done for library that is created once and used many times, but I need a tool that can be used on a daily basis for ordinary code.
One can use Boost.Parameter for ordinary code on a daily basis. We (Boost Consulting) have done it for our major customers and they are *very* satisfied with the results.
it means that simplicity of an implementation should be very close to the solution with auxiliary structures below)
IMO the implementation complexity doesn't matter as long as it works and gives comprehensible feedback when misused. Do you inspect the source code of your compiler and complain about its implementation complexity?
We are living in very different worlds. and it is good for you. I'd be happy if I can say the same as you've said here. Not many of as are paid for libraries writing. My job is application programming. It is always done in a high time pressure. I'm writing several functions per day. Most of them are used only by me to implement other functions. I _can not_ spend time to implement named params for each function that I wrote. It is completely impractical. But I want to have as little amount of bugs in my code as possible. that is why I'm looking for solution that can give me a great amount of safety and be easy to implement for each of a ~10 functions that I wrote per day. The auxiliary struct solution is a good compromise for me and till now I have no problems with it. But this from discussion I learned that it has some drawbacks with the most important for me - inability to specify required parameters at compile time. Now I'm trying to get some ideas from boost community to workaround it somehow.
3) auxiliary structures - mandatory parameters + optional parameters + visible parameters + reuse is possible + no ambiguity with other language constructs + implementation is simple
The last approach with auxiliary structures has only one drawback - it is not possible to have required parameters with it. May be you, David, can see a way how parameter lib can be reused/extended into something like the las solution, but with all '+' marks?
No, and it has more drawbacks. Go back and read the Parameter library review commentary if you want to find all of them.
( I remember additional arguments by Michael Walter:
a) parameter values are copied b) parameter values need to be default-constructable (into a valid state)
but they are not important for me just now )
Well, those are two of the drawbacks, and they count (maybe not for you, but they do count).
May be the best solution that we can have now is:
//implementation: BOOST_PARAM_STRUCT_BEGIN(TFuncParams) BOOST_DECLARE_PARAM_OPTIONAL(type1, name1, def_val1) BOOST_DECLARE_PARAM_REQIRED(type2, name2) BOOST_DECLARE_PARAM_OPTIONAL(type3, name3, def_val3) BOOST_DECLARE_PARAM_OPTIONAL(type4, name4, def_val4) BOOST_PARAM_STRUCT_END()
That's not a nightmare?
It is ugly. Yes. but it is easy to write, remember and understand. Better syntax is welcome
void func(TFuncParams const& params) { cout << params.name1; // etc. }
usage: BOOST_INSTANCIATE_PARAM_STRUCT_BEGIN(TFuncParams, params) BOOST_PARAM_OPTIONAL(params, name1, val1) BOOST_PARAM_REQIRED(params, name2, val2) BOOST_INSTANCIATE_PARAM_STRUCT_END()
func(params);
The idea is that all boost::parameter magic is hidden by those macroses. The question is - can it be really done?
I don't know. The above meets few if any of my requirements for such a library, so determining feasibility will have to fall to someone else.
Anyway, thank you for your attention and reply. Oleg Abrosimov.

"Oleg Abrosimov" <beholder@gorodok.net> wrote in message news:451AACFC.2010308@gorodok.net...
int main() { new_window("alert", width=10, titlebar=false); return 0; }
What is a 'width' here? parameter name? or some variable in global scope?
FWIW heres my suggestion: int main() { new_window("alert", param_name::width=10, param_name::titlebar=false); return 0; } regards Andy little

Oleg Abrosimov <beholder@gorodok.net> writes:
You're not saying what you mean by "reuse." We think reuse is very possible with the Parameter library, so it's quite unclear what you might be referring to.
libraries are all about reuse. boost::parameter is not an exception of course.
By reuse I mean configuration reuse in client code.
By "configuration" I take it you mean something equivalent to "ArgumentPack."
Not reuse of boost::parameter library in other libs. Consider: foo(width = 2, height = 1); // ... some code ... foo(width = 2, height = 3);
vs.
TFooParam p; p.width = 2; p.height = 1; foo(p); // ... some code ... p.height = 3; foo(p); // p is reused here
That's also possible with the parameter library; p would be an ArgumentPack.
The drawback in such a scenario is reduced visibility, because of 'p' can be initialized too far from the second call of 'foo'. But in practice most common scenario is to initialize 'p', call 'foo(p)', then modify 'p' slightly and call 'foo(p)' again. It means that visibility is preserved.
Is that common? For what interface?
- ambiguity with other language constructs (it is very important drawback. As I realized from parameter docs,
You're not being specific enough here either. I can't imagine what ambiguity you mean.
consider:
void new_window(char const* const, int = 10, bool = true);
int main() { int width; bool titlebar; new_window("alert", width=10, titlebar=false); return 0; }
call to new_window can not be translated unambiguously by reader in presence of named params. I expect that compiler will complain, but reader can be fooled by such a call, especially if we change it a bit:
int main() { new_window("alert", width=10, titlebar=false); return 0; }
What is a 'width' here? parameter name? or some variable in global scope?
Oh, sure, Fred Bertsch's problem. Because of that we instituted a new naming convention (and associated macros for defining keyword objects). Now that would read: new_window("alert", _width=10, _titlebar=false);
great effort should be made to make such an ambiguity possible.
Why would we want to make an effort to enable ambiguities?
It would be better IMO to eliminate this efforts in implementation and the ambiguity in one shot - provide special may be auxiliary structure - like syntax to use parameters)
It's unclear what you mean.
I mean that significant amount of work should be done to allow named parameter syntax that can be ambiguous as was shown above.
Why should it?
The idea I was trying to explain is simple - May be it is possible to find a way to achieve both goals - unambiguity and reduce of efforts required to enable named params usage.
I think a suitable naming convention is enough. Or you can use qualification to refer to parameter names.
IMO the implementation complexity doesn't matter as long as it works and gives comprehensible feedback when misused. Do you inspect the source code of your compiler and complain about its implementation complexity?
We are living in very different worlds. and it is good for you. I'd be happy if I can say the same as you've said here. Not many of as are paid for libraries writing. My job is application programming. It is always done in a high time pressure.
That's why you need libraries that work reliably.
I'm writing several functions per day. Most of them are used only by me to implement other functions. I _can not_ spend time to implement named params for each function that I wrote. It is completely impractical.
I agree in principle that it makes little sense to use named parameters in all your internal interfaces. But note, defining a parameter-enabled function hardly takes any time anymore, since Daniel W. created the new macros described in http://www.boost-consulting.com/boost/libs/parameter. It's almost the same as writing down the function would be if there were a built-in language feature. Cheers, -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (8)
-
Andy Little
-
David Abrahams
-
Felipe Magno de Almeida
-
Jeff Garland
-
Jeremy Siek
-
Michael Walter
-
Oleg Abrosimov
-
Robert Ramey