在C ++中调用lambda的哪种方式最惯用?

时间:2014-11-05 10:26:07

标签: c++ lambda function-pointers

我注意到lambdas使用函数指针以及使用function的专用g++类型。

#include <functional>

typedef int(*fptr)(int, int);

int apply_p(fptr f, int a, int b) {
  return f(a, b);
}

int apply_f(std::function<int(int, int)> f, int a, int b) {
  return f(a, b);
}

void example() {
  auto add = [](int a, int b) -> int {
    return a + b;
  };

  apply_p(add, 2, 3); // doesn't give an error like I'd expect it to
  apply_f(add, 2, 3); 
}

我的问题是:哪些是最惯用的?使用一个而不是另一个有什么危险和/或好处?

3 个答案:

答案 0 :(得分:10)

  

我注意到lambdas都使用函数指针和专用的function类型

如果lambda没有捕获任何东西,那么它可以衰减为函数指针。

  

使用哪一种最惯用?

都不是。如果要存储任意可调用对象,请使用function。如果您只想创建并使用它,请保持通用:

template <typename Function>
int apply(Function && f, int a, int b) {
     return f(a,b);
}

您可以更进一步,使返回和参数类型通用;我将此作为练习。

  

使用一个而不是另一个有什么危险和/或好处?

函数指针版本仅适用于(非成员或静态)函数和非捕获lambdas,并且不允许传递任何状态;只有函数本身及其参数。 function类型可以包含任何可调用的对象类型,有或没有状态,因此通常更有用。但是,这有一个运行时成本:隐藏包装类型,调用它将涉及虚函数调用(或类似);并且可能需要动态内存分配来保存大型类型。

答案 1 :(得分:4)

我想说(C ++ 14)

template <class Functor, class... Args>
decltype(auto) apply_functor(Functor&& f, Args&&... args) {
    return std::forward<Functor>(f)(std::forward<Args>(args)...);
}

或C ++ 11:

template <class Functor, class... Args>
auto apply_functor(Functor&& f, Args&&... args) ->decltype(std::forward<Functor>(f)(std::forward<Args>(args)...)) {
    return std::forward<Functor>(f)(std::forward<Args>(args)...);
}

答案 2 :(得分:2)

如果有疑问,请选择std::function

  1. 语法更简单,与其他类型一致,例如

    typedef std::function<int (int, int)> MyAddFunction;
    

    typedef int (*MyAddFunction)( int, int );
    
  2. 它更通用(它实际上可以采用lambda或普通C函数或仿函数)

  3. 它更安全类型

    apply_p(0, 0, 0); // probably crashes at runtime, dereferences null pointer
    apply_f(0, 0, 0); // doesn't even compile