Boost logo

Boost :

From: Oleg Abrosimov (beholder_at_[hidden])
Date: 2006-09-23 12:56:56

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);


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
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

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() :
       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,

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

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.

Boost list run by bdawes at, gregod at, cpdaniel at, john at