如何使用 类 在 C++11 中模拟 lambda 函数和闭包?

How do to simulate lambda functions and closures in C++11 with classes?

假设我有一个积分函数 double integral(double (*f)(double), double a, double b),它计算 f(x) in [a,b] 的积分。但是,我处于 ​​f 在编译时未知的情况,并且可能在运行时发生变化。因此在我目前的设计中,我有一个 class 来跟踪和变异几个 f1, f2, f3 etc.。但是,由于 f1, f2, f3 etc 现在是 class 的成员,我不能只获取它的函数指针 &my_class::f1 并将其提供给 integral(f1,a,b)。这样做的理想方法是在运行时吐出一个 lambda 函数。

一些伪代码可以更准确地说明我想要什么:

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;
}

我仅限于一台只支持C++11的老机器。我的问题分为两部分,在 C++11 中执行此操作的最佳设计是什么,在 g++ 9.2 中最佳设计是什么?

你可以通过integral一个函数模板来解决这个问题,并把一个泛型类型作为函数类型。使用

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

允许您将函数指针和仿函数传递给函数。如果您需要将一个成员函数传递给它,那么您只需将该调用包装到一个 lambda 中,然后将该 lambda 传递给 intergral like

secrete s;
auto result = integral([&s](double a){ return s.f1(a); }, 42.0, 3.14);