Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I construct a functor for use with an algorithm like boost's brent_find_minima?

I am trying to understand why a functor with a constructor cannot be passed to an algorithm, while a functor without a constructor can be.

For the algorithm boost-brent_minima. The example code works fine, when the functor has no constructor:

#include <boost/math/tools/minima.hpp>

struct funcdouble
{
  double operator()(double const& x)
  { //
    return (x + 3) * (x - 1) * (x - 1); // (x + 3)(x - 1)^2
  }
};

int bits = std::numeric_limits<double>::digits;

std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, bits);

std::cout.precision(std::numeric_limits<double>::digits10);
std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;

However, when I use a constructor to generate a custom functor like this:

struct solver_test{

    solver_test::solver_test(std::string expression_string, std::string x_name_) : x_name(x_name_){
        symbol_table.add_constants();       
        symbol_table.create_variable(x_name);
        expression.register_symbol_table(symbol_table);     
        parser.compile(expression_string, expression);
    };

    double operator()(double x) {
        symbol_table.get_variable(x_name)->ref() = x;
        double value = expression.value();
        return value;
    };

    std::string x_name;
    exprtk::symbol_table<double> symbol_table;
    exprtk::expression<double> expression;
    exprtk::parser<double> parser;

};

int bits = std::numeric_limits<double>::digits;

solver_test test_root_finder("(x + 3)(x - 1)^2", "x");
std::pair<double, double> r = boost::math::tools::brent_find_minima(test_root_finder, -4., 4. / 3, bits);

std::cout.precision(std::numeric_limits<double>::digits10);
std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;

I get Compiler Error C2280 - reference deleted function on the line with brent_find_minima. This error also occurs when trying:

std::pair<double, double> r = boost::math::tools::brent_find_minima(solver_test("(x + 3)(x - 1)^2", "x"), -4., 4. / 3, bits);

How can I pass a functor with a constructor, without instantiating it beforehand?

If I look at previous posts

How do C++ functor constructors get called when used with for_each or std::transform

The answers provided don't seem to to be applicable to this case.

like image 906
Chris Avatar asked Oct 12 '16 21:10

Chris


1 Answers

The problem becomes clear if I try

solver_test test_root_finder("(x + 3)(x - 1)^2", "x");
solver_test copy_test = test_root_finder;

Because the functor has no copy constructor it cannot be passed to the algorithm like this:

std::pair<double, double> r = boost::math::tools::brent_find_minima(test_root_finder, -4., 4. / 3, bits);

Adding

solver_test::solver_test(const solver_test &obj) {};

Makes everything OK.

like image 67
Chris Avatar answered Oct 13 '22 00:10

Chris