-->

Using boost::bind to bind member-function to boost

2019-03-02 10:37发布

问题:

I've had problems with this before but now it's somehow working.

Now I've following problem. I need to bind values into member-function before I call boost::bisect with the same function. I found pretty good tutorial and I've followed it but it seems that I'm still doing something wrong.

At first I created test class where I got following working:

std::pair<double, double> result = bisect(&Func, 0.0, 1.0, TerminationCondition());
            double root = (result.first + result.second) / 2;

After that I added binding "on the fly as I thought it could work"

 std::pair<double, double> result = bisect(boost::bind(&CLASS::Function,this, _1), 0.0, 1.000000, TerminationCondition());

Result of that was an error. error: terminate called after throwing an instance of 'boost::exception_detail::clone_impl >' what(): Error in function boost::math::tools::bisect: No change of sign in boost::math::tools::bisect, either there is no root to find, or there are multiple roots in the interval (f(min) = -0.0032916729090909091).

Anyway here is class::function which doesn't work as member function with binding for some reason. I tested it as non-member and it works

double CLASS::Function(double c)
{
/* values: m_a, m_b, m_c, m_d, and m_minus are located in .h file */

normal norm;
double temp = m_d*sqrt(c);

double total = ((1-boost::math::pdf(norm,(m_a*c+m_b)/temp))-(1 - m_c)+boost::math::pdf(norm,(m_a*c+m_b)/temp));

return (total - m_minus); 
}

回答1:

If I read the tutorial correctly, it should be:

std::pair<double, double> result =
    bisect(boost::bind(&CLASS::Function, this, _1, _2, _3),
        0.0, 1.000000, TerminationCondition());

I.e. the parameters to boost::bind() are:

  1. The name of the function (object) to bind to
  2. the arguments to pass to that, as the function expects them

For your case, a CLASS::memberFunc(), that'd be a CLASS * (possibly this but any CLASS * is ok) as the first, which you literally state as such, followed by the parameters later passed to the bound object.

These "futures" are designated by _1, _2 and so on, depending on their position at invocation time.

Example:

class addthree {
private:
    int second;
public:
    addthree(int term2nd = 0) : second(term2nd) {}
    void addto(int &term1st, const int constval) {
        term1st += (term2nd + constval);
    }
}

int a;
addthree aa;
boost::function<void(int)> add_to_a = boost::bind(&addthree::addto, &aa, a, _1);
boost::function<void(void)> inc_a = boost::bind(&addthree::addto, &aa, a, 1);

a = 0 ; add_to_a(2); std::cout << a << std::endl;
a = 10; add_to_a(a); std::cout << a << std::endl;
a = 0 ; inc_a(); std::cout << a << std::endl;
[ ... ]


回答2:

This code:

std::pair<double, double> result = bisect(boost::bind(&CLASS::Function,this, _1), 0.0, 1.000000, TerminationCondition());

is correct. The error you get means that what CLASS::Function returns is invalid. bisect is complaining about multiple roots (or possibly no roots) in the given interval [0; 1]. How does CLASS::Function look like?