Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ calling a class function inside another function

I am trying to call an outside function (that takes functions as inputs) inside the class by giving class member functions as it's parameters. My code is as follows:

using namespace std;
// This is my external function
double integrate (double a, double b, int steps, double (*func)(double)){
    // code for integration using function pointer
};

Class A
{
    protected:
        vector<double> to_data, from_data;
        int data_size;

    public:
        A (); // constructor

        double calculate_parameter(double t){
            // some class member function that makes use of other class members
        };

        double get_result(double x){
            double sum = 0;
        for (int i=0;i<data_size;i++){
           // this is basically what causes the error
            sum = sum + integrate(to_data[i],from_data[i],1,calculate_parameter);
        }
 };

}

However, it shows me error that the function calculate_parameter cannot be converted. I figured out a way to solve this would be to modify the external function such that it takes a class object as well. Is there a way to do this without instantiating a new class object? Thanks in advance!

like image 789
AnotherCodingEnthusiast Avatar asked Jan 10 '23 05:01

AnotherCodingEnthusiast


1 Answers

The more general approach is to drop these 1970s function pointers and use technology from this millennium:

#include <functional>

double integrate (double a, double b, int steps, std::function<double(double)> f)
{
    // ...
}

class A
{
    double calculate_parameter(double t);

    double get_result(double x)
    {
        using std::placeholders::_1;

        double sum = 0;
        for (int i = 0; i < data_size; i++) {
            sum = sum + integrate(
                to_data[i],
                from_data[i],
                1,
                std::bind(&A::calculate_parameter, this, _1)
            );
        }

        return sum;
    }
};

This provides a simple and easy way to bind to essentially any kind of function, and to "bake in" the this pointer for member functions to the functor itself, without requiring any magic at the eventual callsite (i.e. within integrate, which literally just has to call f!).


An even more "modern" way to do this is to wrap the call to calculate_parameter in a lambda:

template <typename Callable>
double integrate (double a, double b, int steps, Callable f)
{
    // ...
}

class A
{
    double calculate_parameter(double t);

    double get_result(double x)
    {
        double sum = 0;
        for (int i = 0; i < data_size; i++) {
            sum = sum + integrate(
                to_data[i],
                from_data[i],
                1,
                [this](double x) { return this->calculate_parameter(x); }
            );
        }

        return sum;
    }
};

Notice that I've replaced std::function<double(double)> with a deduced template argument Callable; you don't have to do this, but it's conventional not to force a lambda-to-std::function conversion when you don't have to. (Personally I quite like being able to mandate that f will take a double and return a double, without having to rely on its usage to check this.)

like image 119
Lightness Races in Orbit Avatar answered Jan 17 '23 22:01

Lightness Races in Orbit