|
Boost Users : |
Subject: Re: [Boost-users] [lamda] smart self binding of a function object
From: OvermindDL1 (overminddl1_at_[hidden])
Date: 2010-05-12 04:42:30
On Tue, May 11, 2010 at 4:11 AM, alfC <alfredo.correa_at_[hidden]> wrote:
> Hi,
>
> Â I usually have function-classes that take two arguments.
>
> class f{
> Â double operator()(double x, double y) const { x*y+y; }
> };
>
> called as:
>
> f myf;
> cout << myf(4.,3.);
>
> for some purposes I need a function of only one variable (parametrized
> in the first or second argument. So I end up doing:
>
> using boost::function;
> using namespace boost::lambda;
> function<double(double)> myf_at5 = bind(&f::operator(), myf, 5., _1);
> // myf_at5 is myf(5.,*)
>
> So, now I can pass myf_at5 to something that accepts a function of one
> variable.
>
> root_finder( myf_at5, ...);
>
> since I have access to f I would like to make f smart enough to handle
> its own binding. Eg.
>
> class f{
> Â ... // same as before
> Â function<double(double)> operator()(double x_value, YYYY y_arg){
> Â return bind(
> Â Â Â Â &f::operator(), //maybe needs cast to double(*)
> (double,double)
> Â Â Â Â *this,
> Â Â Â Â x_value,
> Â Â Â Â y_arg
> Â );
> Â }
> Â function<double(double)> operator()(XXXX x_arg, double y_value){
> Â return bind(
> Â Â Â &f::operator(), //maybe needs cast
> Â Â Â *this,
> Â Â Â x_arg,
> Â Â Â y_value
> Â );
> Â }
> };
>
> The question is: What should be the type of XXXX and YYYY?
>
> in such a way that I can just call
>
> root_finder( myf(5., _1) , ... );
> or
> more complicated things like
> root_finder( myf(5., _1 * 2.), ...);
>
> in other words,
> myf(5.,_1) is the same as the old  bind(&f::operator(), myf, 5., _1);
The way I would do this would be Boost.Phoenix, rewrite your f like (I
am not making this fully generic, although it would be easy to do,
just keeping it as doubles):
class f_impl{
template <typename Arg1, typename Arg2>
struct result
{
typedef double type;
};
double operator()(double x, double y) const { x*y+y; }
};
boost::phoenix::function<f_impl> f;
This turns f into a lazy functor, thus for immediate usage you can do:
cout << f(4.,3.)(); // Assuming Phoenix3 (in development) with
forwarding built-in, so no val's needed.
or
f_impl myf;
cout << myf(4.,3.);
But allows lazy generation like:
root_finder( f(5., _1) , ... );
or
root_finder( f(5., _1 * 2.), ...);
If curious, Boost.Phoenix can do what lambda can, but more, it is a
generic lazy extension for C++, even something as simple as:
val(5)
that essentially returns a function of the type int(void), so:
cout << val(5)();
return 5 to cout. Obviously a bit of an inconvenience that the
immediate form returns a lazy adapter too, but it is the pure lazy
way, but allows for a vast amount of power and programming
capabilities.
(I have even written a few small programming projects completely in
Boost.Phoenix to see what it is like, quite fascinating, I do like it,
just hits compile time a bit hard when everything is lazy in an entire
program, but runs well).
Boost.Phoenix2 docs:
http://www.boost.org/doc/libs/1_43_0/libs/spirit/phoenix/doc/html/index.html
Boost.Phoenix3 is in development, but Phoenix2 is complete, just
missing the 'perfect' forwarding adaption.
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