Подтвердить что ты не робот

Обратный вызов против лямбда

Предположим, у меня есть следующий код, который я хочу реорганизовать:

int toFuture()
{
  precalc();
  int calc = 5 * foobar_x() + 3;
  postcalc();
  return calc;
}

int toPast()
{
  precalc();
  int calc = 5 * foobar_y() - 9;
  postcalc();
  return calc;
}

В классическом C я бы реорганизовал этот код в employee(), который принимает указатель на функцию, который выполняет вычисление: общий код в worker(), определенный код, предоставляемый указателем функции.

С С++ 11, следует ли вместо этого использовать лямбда? Если да, то как бы реализовать его в этом случае?

Изменить: мне просто пришло в голову, что шаблон также может работать. Как реализация шаблона сравнивается с двумя другими?

4b9b3361

Ответ 1

Один подход:

template<typename CalcFuncT>
int perform_calc(CalcFuncT&& calcfunc)
{
    precalc();
    int const calc = std::forward<CalcFuncT>(calcfunc)();
    postcalc();
    return calc;
}

int main()
{
    perform_calc([]{ return 5 * foobar_x() + 3; }); // toFuture
    perform_calc([]{ return 5 * foobar_y() - 9; }); // toPast
}

Ответ 2

Если вы хотите использовать шаблонный подход с использованием возможностей С++ 11, это может выглядеть так просто:

template<typename FuncType>
auto calculation(FuncType&& func) -> decltype(func())
{
    precalc();
    auto ret = func();
    postcalc();
    return ret;
}

Затем вы просто вызываете свою функцию calculation и передаете ее либо лямбдой, либо функтором, либо указателем функции. Ваш единственный недостаток сложности в этом случае был бы, если бы вы передали функцию с void return-type... в этом случае вы получите ошибку компилятора (что является хорошей вещью и ошибкой во время выполнения).

Ответ 3

Я бы сказал, что вы рефакторинг с неправильной стороны:

struct CalcGuard {
  CalcGuard() { /* replaces precalc() */ }
  ~CalcGuard() { /* replaces postcalc() */ }
};

int toFuture()
{
  return CalcGuard(), calc = 5 * foobar_x() + 3;
}

int toPast()
{
  return CalcGuard(), calc = 5 * foobar_y() - 9;
}

Ответ 4

Существует способ C/C++ сделать это и C++11. Ни один из способов не включает в себя лямбды или шаблоны.

Способ C/C++:

double MyFunc (int x, float y) { return x + y ; }

int main()
  {
  double (*pf) (int, float) ;
  pf = MyFunc ;
  pf (101, 202.0) ;
  }

Способ C++11:

#include <functional>

double MyFunc (int x, float y) { return x + y ; }

int main()
  {
  std::function<double (int, float)> f ;
  f = MyFunc ;
  f (51, 52.0) ;
  }

В любом случае вы просто передаете pf или f в свою рефакторированную функцию в качестве параметра. Использование lambdas или шаблонов здесь слишком велико.