Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2001-03-07 05:41:07


Paul Moore wrote:
> It seems to me that the intent is to simulate named
> parameters for templates
> which have a number of (relatively) unrelated arguments.

The intent is to improve the library's usability and make the usage less
error prone. As Dave already said, the 'iterator_adaptor' class template has
7 template parameters, and 5 of them are default - the known situation with
known problems and solutions if you replace "template" with "function"
(except that it's actually more error prone in case of templates, as in
general it is harder to diagnose an invalid order of the template arguments,
and compiler does not offer much help here). For instance, there is a common
knowledge how to bring something like

graphics::font f(make_font(font_type::true_type_font, "",
font_charset::default_charset, 10, 700, false, false, false,
font_family::script));

to a much more acceptable (in many aspects) state:

graphics::font f(font_properties()
  .size(10)
  .bold(true)
  .family(font_family::script)
  );

The first form is sort of "traditional" C API, but I in no way will write
something like this in my code, and I hope that you won't argue in favour of
it too ;). The point is that template classes with many parameters and
default values are as clumsy and unmaintable as these C-style interfaces (if
not more), and if proof by analogy is not enough for someone, I think that
many of us who walked long enough way with templates to feel it once more
can say for themselves. That is important, that there is already approved by
time and experience solution for the problem in its "traditional" form, and
"named template parameters" are just a translation of this solution to
another domain.

BTW, the default parameters of 'iterator_adaptor' template *are* related (as
are the members of the 'font_properties' class from the above example, and
pretty much of all properties/builder classes); essentially together they
form custom 'iterator_traits' that were unfolded into list because there
were no simple way to construct that structure "inline".

> While this is not a
> problem to me in principle, I feel that the following points
> are important
> to remember:
>
> 1. C++ doesn't have named parameters. Any method for
> simulating them must of
> necessity be clumsier than a built in language construct.
> This clumsiness
> will be visible to the user.

First of all, it's not about simulating the missing feature, it's about
solving the real problem in an acceptable way. Second, I don't think that

iterator_traits_builder
  ::value<dummyT>
  ::reference<const dummyT&>
  ::category<std::forward_iterator_tag>
  ::distance<std::ptrdiff_t>
  ::pointer<const dummyT*>
  ::type

is so much different from

iterator_traits_builder<
    value = dummyT
  , reference = const dummyT&
  , category = std::forward_iterator_tag
  , distance = std::ptrdiff_t
  , pointer = const dummyT*
>

IMO they are pretty much equivalent in both readability and ability to
express the code intent.

>
> 2. Even in languages with named parameters, they are not always used.
> Personal preference and/or application requirements (for
> clarity of code)
> have a significant impact on the decision.

Yes, there should be a way to use the usual syntax.

>
> As such, I feel that it is important to ensure that in simulating the
> ability to call of f(a,b,c) [I'm using functions rather than
> templates here
> to keep the example simple, not because I believe that this
> discussion is in
> any way related to function calls!!!] as f(a=1, b=2, c=3) or f(c=2) or
> f(c=1, a=2), we must make sure NOT to lose the ability to call it as
> f(1,2,3) or even f(1,2).

I agree. There are situations then positioning of default parameters exactly
matches the template's usage pattern and in these cases the traditional way
is less verbose.

> My personal view is that I would (nearly always) use the
> positional usage,
> rather than the named parameter usage, mainly for consistency
> with the rest
> of the language.

"Nearly always" IMO is a very strong phrase, even when one is speaking about
his own personal preferences ;). For the "classical" template code, e.g.
STL, this may be very true, but 'iterator adaptors' library is something
quite different from STL, at least in its usage patterns and level of
parameterization / metaprogramming. As the number of such libraries,
including some of boost, will grow, the need for the techniques like NTP
will grow too, and they will become very common.

> Hence, if the iterator adaptors library
> forced me to use
> named parameters, I would have an annoying and difficult
> learning/acceptance
> curve to climb.
>
> While the technique is certainly clever, let's not get overly
> impressed by
> the cleverness, at the expense of consistency and simplicity.

Again, it's not about cleverness/coolness/whatever. It's about moving
forward things that need to be moved because they are in a
near-to-unacceptable state now.

Aleksey


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