Boost logo

Boost Users :

Subject: [Boost-users] [fusion] named parameter technique with fusion::map
From: alfC (alfredo.correa_at_[hidden])
Date: 2010-11-06 08:19:08


Hi,

 After I discovered Boost.Fusion I realize that I can define proper
named functions with Boost.Fusion. Named in the sense of
instrospection (not in the sense of default user parameters). It was
something that is easy to achieve but it was very verbose. I
simplified a little bit the syntax but at the end I got stuck just
before achieving something useful with this ideas. I need a little
help towards the end.

using namespace boost::fusion;
double H(double p, double q){ // original function for reference
        return p*p + q*q;
}
struct p{};
struct q{};
double H(map<pair<p, double>, pair<q, double> > const& args){
        return H(at_key<p>(args), at_key<q>(args));
}
int main(){
cout << H(
 map<pair<p, double>, pair<q, double> >(
    make_pair<p>(1.),
    make_pair<q>(2.)
 )
);
return 0;
}

One question: Why I can not interchange the order of p and q in the
last call, after all it is a map at the library could in principle
differentiate the pairs? making it possible to call an unordered named
parameter. e.g.
cout << H(
 map<pair<p, double>, pair<q, double> >(
    make_pair<q>(2.), // was p
    make_pair<p>(1.) // was q
 )
);
Is it possible to interchange the order to give more flexibility to
the user?

After a little playing I gladly found that the make_pair is not
stricly necesary
cout << H(
 map<pair<p, double>, pair<q, double> >(1.,2.)
);
which is a nice improvement. It seems that still there is some
redundancy, so I tried

cout << H(make_map<p, q>(1.,2.));

and worked!

On the side of the function definition I can have an alternative
syntax which may be shorter but more difficult to interpret:

double H(result_of::make_map<p, q, double, double>::type const& args)
{ ... }
although it is not a great improvement.

Second question: Does it occur to anyone how simplify things further?

This is nice because *in principle* I can distinguish between the two
parameters (strictly speaking is all one big parameter) at compile
time via templates.

Third question: I say in principle because I am stuck here. For
example how can I implement a named parameter bind? It seems to me
that I am close to achieving this but I don't know exactly how. What I
want is some kind of "bind<H, q>(3.0)" which is a function object that
effectively evaluates to H( pvalue, 3.0) or to
H(make_map<p>(pvariable), 3.0) when calling bind<H, q>(3.0)(pvalue) or
bind<H, q>(3.0)(make_map<p>(pvalue)). Note that the most general case
is something that defines partial parameters by a map
//if H had four parameters:
auto b = my::bind<H, set<q1, q2> >( make_map<q1, q2>(3.0, 4.0) ) ;
// or my::make_bind<H>( make_map<q1, q2>(3.0, 4.0) )
// and then use it as
b(make_map<p1, p2>(5.0,6.0));

I think this seems to be promising although I need a little push to
finish the technique I hope it is useful for someone (if I am not
reinventing the wheel) and that we can round up the idea. or just
wanted to know some opinions.

Thank you,
Alfredo

(Note, named parameter boost library is not the proper way to go here
because the of the level of instrospection I need in the functions,
and because the use of named parameters is not to omit passing
parameters but to recognize 'externally' certain parameters).


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net