0

Let's say I have an integration function double integral(double (*f)(double), double a, double b) which computes the integral of f(x) in [a,b]. However, I am in a situation where f is not known in compile time, and may change during runtime. Therefore in my current design, I have a class that tracks and mutates several f1, f2, f3 etc.. However, since f1, f2, f3 etc are now a member of a class, I can't just take its function pointer &my_class::f1 and feed it to integral(f1,a,b). The ideal way of doing this would be to just spit out a lambda function during runtime.

Some pseudo code to be more precise about what I want:

double integral(double (*f)(double), double a, double b);

class secret {
  public:
    // all three of these rely on internal state that this class manages
    // absolutely none of these methods can be static!
    double f1(double x);
    double f2(double x);
    double f3(double x);

    void do_stuff(); // mutates internal state, changing the behavior of f1,f2,f3
    void do_something_else(); // mutates internal state, changing the behavior of f1,f2,f3
    double execute(); // internally, this function calls integrate(f1,a,b), integrate(f2,a,b) and integrate(f3,a,b)
}

// needs to handle functions that are not part of a class
double quadratic(double x) {
  return x*x;
}

int main() {
   secret s1, s2;
   s1.do_stuff() // change the state of s1, changing f1,f2,f3
   s2.do_something_else() // change the state of s2. 
   // We can have multiple instances of the secret class, all with different internal state, 
   // but need the ability to call "integral" with a lot of freedom

   // I want a good design that will let me do this kind of thing
   cout<<integrate(&s1.f1, 0, 1)<<endl;
   cout<<integrate(&quadratic, 0, 1)<<endl;
   cout<<integrate(&s2.f1, 0, 1)<<endl;
   cout<<s1.execute()<<endl;
   cout<<s2.execute()<<endl;
}

I am limited to an old machine that only supports C++11. My question is in two parts, what is the best design to do this in C++11, and what is the best design in g++ 9.2?

6
  • 5
    You can use lambdas to "simulate lambda functions" in C++11. Commented Jan 14, 2020 at 19:36
  • 1
    lambda's are available in C++11, right? Commented Jan 14, 2020 at 19:39
  • 1
    "Lambda expressions (since C++11)": en.cppreference.com/w/cpp/language/lambda Commented Jan 14, 2020 at 19:40
  • How do closures work in C++11? Can those lambda functions access class members of the instantiated class? Commented Jan 14, 2020 at 19:42
  • @SpentDeath Lambdas can capture variables from its environment, yes. Commented Jan 14, 2020 at 19:43

1 Answer 1

1

You can solve this by making integral a function template and take a generic type as the function type. Using

template <typename Func>
double integral(Func func, double a, double b)
{
    auto result = func(a);
    // do something with result
    return result;
}

Allows you to pass function pointers and functors to the function. If you need to pass a member function to it, then you just wrap that call into a lambda and then pass that lambda to intergral like

secrete s;
auto result = integral([&s](double a){ return s.f1(a); }, 42.0, 3.14);
Sign up to request clarification or add additional context in comments.

2 Comments

This is exactly what I was looking for. Related question:auto blah = [&s](double a){ return s.f1(a); }; if (some_statement) { blah = [&s](double a){ return s.f2(a);} blah();} How can I make assignments with lambdas like this?
@SpentDeath Use a std::function instead of auto. Then you can reassign it. It cost some more since it uses type erasure but it basically the only way to do it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.