обратный звонок против лямбды - PullRequest
26 голосов
/ 20 октября 2011

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

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

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

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

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

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

Ответы [ 4 ]

40 голосов
/ 20 октября 2011

Один подход:

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
}
22 голосов
/ 20 октября 2011

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

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

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

7 голосов
/ 20 октября 2011

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

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;
}
1 голос
/ 20 октября 2011

Существует способ 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к вашей рефакторированной функции в качестве параметра.Использование лямбды или шаблонов здесь излишне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...