Как симулировать лямбда-функции и замыкания в C ++ 11 с помощью классов? - PullRequest
0 голосов
/ 14 января 2020

Допустим, у меня есть функция интегрирования double integral(double (*f)(double), double a, double b), которая вычисляет интеграл от f(x) in [a,b]. Однако я нахожусь в ситуации, когда f неизвестно во время компиляции и может измениться во время выполнения. Поэтому в моем текущем дизайне у меня есть класс, который отслеживает и изменяет несколько f1, f2, f3 etc.. Однако, поскольку f1, f2, f3 etc теперь является членом класса, я не могу просто взять указатель на его функцию &my_class::f1 и передать его в integral(f1,a,b). Идеальный способ сделать это - просто выпустить лямбда-функцию во время выполнения.

Некоторый псевдокод, если быть более точным, о том, что я хочу:

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?

1 Ответ

1 голос
/ 14 января 2020

Вы можете решить эту проблему, сделав integral шаблоном функции, и в качестве типа функции выберите тип c. Использование

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

Позволяет передавать указатели функций и функторы в функцию. Если вам нужно передать ему функцию-член, то вы просто заключаете этот вызов в лямбду, а затем передаете эту лямбду в intergral как

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