回调vs lambda

时间:2011-10-19 21:54:13

标签: c++ lambda c++11

假设我有以下要重构的代码:

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,我应该使用lambda吗?如果是这样,在这种情况下我将如何实现它?

编辑:我突然意识到模板也可以运作。模板实现如何与其他两个进行比较?

4 个答案:

答案 0 :(得分:40)

一种方法:

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
}

答案 1 :(得分:22)

如果您想要使用C ++ 11功能的模板方法,可能看起来很简单:

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

然后,您只需调用calculation函数并将其传递给lambda,functor或函数指针。在这种情况下,你唯一的困难就是如果你传递了一个void返回类型的函数......在这种情况下你会得到一个编译器错误(这对运行时错误是一件好事)

答案 2 :(得分:7)

我说你是从错误的方面重构:

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

答案 3 :(得分:1)

有一种C/C++方式可以执行此操作,并采用C++11方式。这两种方式都不涉及lambdas或模板。

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

在任何一种情况下,您只需将pff作为参数传递给重构函数即可。使用lambdas或模板在这里是过度的。