
On Tue, May 11, 2010 at 4:11 AM, alfC <alfredo.correa@gmail.com> 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.