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!
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With