|
Boost : |
From: Doug Gregor (dgregor_at_[hidden])
Date: 2004-11-17 18:20:07
I've just implemented a new BGL algorithm using the named parameters
library for the interface. The algorithm itself is very simple, but
illustrates some of the benefits and pitfalls of the named parameters
library.
After writing this, I of course have some questions and comments about
the named parameters library.
This is not actually a review: that will come later. And don't confuse
this with my role as review manager.
--------------------------Fixed positional
parameters-----------------------------
The first issue I ran into was that I really wanted a fixed number of
positional parameters before any of the named parameters. These
parameters will not have defaults and there is no reason to allow them
to have names. I say this is an "issue" and not a "problem" because
there are several workarounds:
1) Don't use BOOST_NAMED_PARAMS_FUN; write out the forwarding
functions manually. (This is the option I chose)
2) Make the required, positional parameters into named parameters (so
that we can use BOOST_NAMED_PARAMS_FUN) but do not provide the objects
of type "keyword" for these parameters. So, for instance, I'll have
"struct graph_t {};" but no corresponding keyword
"boost::keyword<graph_t> graph;". The algorithm would also have to use
boost::named_param to say that there is no default value for these
parameters.
I chose option (1) for various reasons. The primary reason actually had
to do with something another reviewer brought up: it's rather hard to
deal with creating defaults for named parameters that rely on other
named parameters. This was never easy (the BGL has the same problem),
but picking (2) above makes things much harder: for instance, the first
positional parameter is _always_ the graph, and nearly every default
value depends on knowing the graph type. However, I wouldn't be able to
get at the type of p[graph_t()] without passing it to another helper
function and doing the work there.
------------------------Default parameters----------------------
Both normal and lazy defaults work very cleanly. The dispatch to my
implementation function is quite readable:
detail::page_rank_impl
(g,
rank_map,
p[done | n_iterations(20)],
p[num_active_vertices | num_vertices(g)],
p[rank_map2
|| vector_property_map_builder<Graph, rank_type>(g)]);
vector_property_map_builder is a new function object a had to create to
perform the lazy construction of a vector_property_map, but that
doesn't hurt so badly. A better version of it would just end up
somewhere in the BGL and be reused.
-----------------------The type of params[foo | def]-------------------
Going into this, I had the notion that I'd be able to use
BOOST_NAMED_PARAMS_FUN to eliminate all of the extra levels of
dispatching calls. It still took 3 levels of function calls: 1 for
bundle the parameters, one to stick defaults in, and one to do the
actual work. If we could get the return type of p[foo | def] or p[foo
|| def] directly, we could solve those problems. To make that usable,
perhaps some"auto"-like macro:
BOOST_NAMED_PARAMS_AUTO(g, graph_t);
BOOST_NAMED_PARAMS_AUTO_DEF(done, done_t, n_iterations(20));
BOOST_NAMED_PARAMS_AUTO_LAZY_DEF(rank_map2, rank_map2_t,
(vector_property_map_builder<Graph,
rank_type>(g)));
Unfortunately, I think we need typeof to do that :)
----------------------- Question on boost::keyword -------------------
If the BGL is going to switch to this library, we are going to need
backward compatibility. I can do that easily if I'm allowed to derive
my keywords from boost::keyword instead of using exactly a
"boost::keyword". Can I do that?
More comments and probably a real review later... I want to go home now.
Doug
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk