comments inline... alfC schrieb:
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 > const& args){ return H(at_key<p>(args), at_key<q>(args)); } int main(){ cout << H( map, pair >( 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 >( 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?
I don't think that this is a good idea. Reordering is a quite expensive operation and it would really slow down compile times. On top of that, fusion::map is a forward sequence which has a definite order (!) on its elements. Reordering does not feel natural here. Having that said, you can easily write your own, reordering associative sequence or you can construct your map from another another fusion sequence that you reorder on the fly, for example via fusion::nview .
After a little playing I gladly found that the make_pair is not stricly necesary cout << H( map
, pair >(1.,2.) ); which is a nice improvement. It seems that still there is some redundancy, so I triedcout << H(make_map
(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
::type const& args) { ... } although it is not a great improvement.
Second question: Does it occur to anyone how simplify things further?
Check the attached main.cpp!
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
(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 (3.0)(pvalue) or bind (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 >( make_map (3.0, 4.0) ) ; // or my::make_bind<H>( make_map (3.0, 4.0) ) // and then use it as b(make_map (5.0,6.0));
I do not understand that. There is a bind example in libs/fusion/example/cookbook/do_the_bind.cpp . Proto might be more helpful here, though.
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).
-Christopher