1174
1174

Reputation: 131

boost::function on member functions

I am trying to make use of the boost::function, I am a newbie on C++ and doing a course.

What I have:

class OptionPricer {
    [constructor etc..]
    double CallPrice(const double S);
    double PutPrice(const double S);
    double CallPrice(const double S, const double putPrice);
    double PutPrice(const double S, const double callPrice);
    vector<double> OptionPricer::Mesher(const double start, const double end, const double h, boost::function<double (const double)> funct);
};

I would like to use boosts function pointers so I do not have to replicate the Mesher function, instead just passing the *Price functions.

What I try to do:

boost::function<double (double)> functCP = &OptionPricer::CallPrice;

But I get:

ClCompile: OptionPricer.cpp Main.cpp c:\c++\9.a.1\9.a.1\main.cpp(34): error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'boost::function' with [ Signature=double (double) ] No constructor could take the source type, or constructor overload resolution was ambiguous

I also tried without the addressof operator but my experience is too little to understand this type of issue in full extent. If someone can advise it would be great.

Thank you for the comments, I tried the const double as well before.

Given the advise I tried this now, which works, out of that another question arises.

I got this now, after advise from Mike Seymour:

    // Calculate meshes 
    double start = 0, end = 20, h = 0.5;
    boost::function<double (const double)> functCP = boost::bind(&OptionPricer::CallPrice, &pricer1, _1);
    boost::function<double (const double)> functPP = boost::bind(&OptionPricer::PutPrice, &pricer1, _1);
    cout << "Calculate meshes:" << endl;
    cout << "Mesh1 Call: " << pricer1.Mesher(start, end, h, functCP) << " Mesh1 Put: " << pricer1.Mesher(start, end, h, functPP) << endl;
    cout << "Mesh2 Call: " << pricer2.Mesher(start, end, h, functCP) << " Mesh2 Put: " << pricer2.Mesher(start, end, h, functPP) << endl;
    cout << "Mesh3 Call: " << pricer3.Mesher(start, end, h, functCP) << " Mesh3 Put: " << pricer3.Mesher(start, end, h, functPP) << endl;

Why I did not want to use an instance was because I would then need to bind it to all 3 pricer instances, they contain the data to build the mesh from e.g. they differ in their instance values, I think I might need to make the bind more dynamic somehow.

E.g. above function is not correct since I use only pricer1 function bindings on pricer2 and pricer3 instances.

What I would do at current stage is duplicating that for pricer2, pricer3 etc. Actually I wanted to get rid of redundancy and not duplicate the mesher since it is just iterating over a range, now I still have kind of duplication but definitely better than having a kind of duplication on the function side.

boost::function<double (const double)> functCP = boost::bind(&OptionPricer::CallPrice, &pricer2, _1);
boost::function<double (const double)> functPP = boost::bind(&OptionPricer::PutPrice, &pricer2, _1);

Got rid of redundancy, might not be the most technical solution but:

boost::function<double (const double)> bindCPricer(OptionPricer &pricer) {
    return boost::bind(&OptionPricer::CallPrice, &pricer, _1);
}

boost::function<double (const double)> bindPPricer(OptionPricer &pricer) {
    return boost::bind(&OptionPricer::PutPrice, &pricer, _1);
}

cout << "Mesh1 Call: " << pricer1.Mesher(start, end, h, bindCPricer(pricer1)) << " Mesh1 Put: " << pricer1.Mesher(start, end, h, bindPPricer(pricer1)) << endl;
    cout << "Mesh2 Call: " << pricer2.Mesher(start, end, h, bindCPricer(pricer2)) << " Mesh2 Put: " << pricer2.Mesher(start, end, h, bindPPricer(pricer2)) << endl;

Thank you very much for your input!

Btw. I have been programming Java for more than 10 years, I am wondering why I haven not learnt C++ earlier, so far it looks much more powerful to me, boost is awesome, templating is also more sophisticated than Java Generics.

Upvotes: 0

Views: 1910

Answers (1)

Mike Seymour
Mike Seymour

Reputation: 254431

The function object needs to be called on its own, while a member function needs an object. So you'll need to bind it to one:

OptionPricer pricer; // The object you want the function to use
boost::function<double (double)> functCP = 
    boost::bind(&OptionPricer::CallPrice, &pricer, _1);

This binds the function to a pointer to pricer, so that calling the function functCP(x) is equivalent to pricer.CallPrice(x). Beware that, if the object is copyable, it's easy to accidentally bind to a copy of it, which probably isn't what you want.

Alternatively, in modern C++, you could use a lambda (and you'd also use the standard library rather than Boost):

std::function<double (double)> functCP = 
    [&pricer](double x){return pricer.CallPrice(x);};

I find that more readable than a bind expression; your aesthetics may differ.

Upvotes: 2

Related Questions