C++ 如何声明接受lambda的函数?

C++ 如何声明接受lambda的函数?,c++,lambda,c++11,C++,Lambda,C++11,我在互联网上阅读了许多教程,解释了如何将lambda与标准库一起使用(例如std::find),它们都非常有趣,但我找不到任何教程解释了如何将lambda用于我自己的函数 例如: int main() { int test = 5; LambdaTest([&](int a) { test += a; }); return EXIT_SUCCESS; } 我应该如何声明LambdaTest?它的第一个参数是什么类型的?然后,我如何调用传递给它的匿名函数?例如,

我在互联网上阅读了许多教程,解释了如何将lambda与标准库一起使用(例如
std::find
),它们都非常有趣,但我找不到任何教程解释了如何将lambda用于我自己的函数

例如:

int main()
{
    int test = 5;
    LambdaTest([&](int a) { test += a; });

    return EXIT_SUCCESS;
}

我应该如何声明
LambdaTest
?它的第一个参数是什么类型的?然后,我如何调用传递给它的匿名函数?例如,“10”作为其参数?

鉴于您可能还希望接受lambda之外的函数指针和函数对象,您可能希望使用模板来接受任何带有
操作符()的参数。这就是像find这样的std函数所做的。它看起来是这样的:

template<typename Func>
void LambdaTest(Func f) {
    f(10);
}
模板
无效LambdaTest(函数f){
f(10);
}

注意,这个定义没有使用任何c++0x特性,所以它完全向后兼容。只有使用特定于c++0x的lambda表达式调用函数。

如果不想对所有内容进行模板化,可以执行以下操作:

#include<functional> 

void LambdaTest (const std::function <void (int)>& f)
{
    ...
}
#包括
void LambdaTest(const std::function&f)
{
...
}

我想提供这个简单但不言自明的例子。它展示了如何将“可调用的东西”(函数、函数对象和lambda)传递给函数或对象

// g++ -std=c++11 thisFile.cpp

#include <iostream>
#include <thread>

using namespace std;

// -----------------------------------------------------------------
class Box {
public:
  function<void(string)> theFunction; 
  bool funValid;

  Box () : funValid (false) { }

  void setFun (function<void(string)> f) {
    theFunction = f;
    funValid = true;
  }

  void callIt () {
    if ( ! funValid ) return;
    theFunction (" hello from Box ");
  }
}; // class

// -----------------------------------------------------------------
class FunClass {
public:
  string msg;
  FunClass (string m) :  msg (m) { }
  void operator() (string s) {
    cout << msg <<  s << endl; 
  }
};

// -----------------------------------------------------------------
void f (string s) {
  cout << s << endl;
} // ()

// -----------------------------------------------------------------
void call_it ( void (*pf) (string) ) {
  pf( "call_it: hello");
} // ()

// -----------------------------------------------------------------
void call_it1 ( function<void(string)> pf ) {
  pf( "call_it1: hello");
} // ()

// -----------------------------------------------------------------
int main() {

  int a = 1234;

  FunClass fc ( " christmas ");

  f("hello");

  call_it ( f );

  call_it1 ( f );

  // conversion ERROR: call_it ( [&] (string s) -> void { cout << s << a << endl; } );

  call_it1 ( [&] (string s) -> void { cout << s << a << endl; } );

  Box ca;

  ca.callIt ();

  ca.setFun (f);

  ca.callIt ();

  ca.setFun ( [&] (string s) -> void { cout << s << a << endl; } );

  ca.callIt ();

  ca.setFun (fc);

  ca.callIt ();

} // ()
//g++-std=c++11 thisFile.cpp
#包括
#包括
使用名称空间std;
// -----------------------------------------------------------------
类框{
公众:
功能的功能;
布尔·芬沃德;
框():funValid(false){}
void setFun(函数f){
函数=f;
funValid=true;
}
空卡利特(){
如果(!funValid)返回;
函数(“来自方框的您好”);
}
}; // 班
// -----------------------------------------------------------------
类函数类{
公众:
串味精;
FunClass(字符串m):msg(m){}
void运算符()(字符串s){

cout如果出现错误,错误消息将很难理解。这取决于它是否是最好的。这使用了一个模板,而另一个不使用。这意味着函数不能再是虚拟的,不能在cpp文件中单独定义。
std::function
也完全能够接受函数对象类类型,尽管调用时会稍微慢一点。但对于大多数应用程序来说,这种差异可以忽略不计:)“最佳”在旁观者眼里:-)这个答案使用了一个
functor,这很好,但并没有真正回答最初的问题(以及是什么导致我这样做的),即“如何将lambda用于我自己的函数?”。此外,模板也有自己的一套问题,而
std::function
的答案则没有。@Marco这个答案不需要你使用functior,它允许你使用任何你想要的东西,包括lambdas。这个语法实际上允许我保存函数变量以便以后调用,对吗?例如,我想实现一个function它允许执行异步数据库查询,其中lambda充当回调函数。(当然,我不能通过引用访问闭包)按值传递函数不是更惯用吗?@Andreas Bonini:是的,如果保存到
std::function
(不是引用),您可以复制
f
。但是,我不确定当引用的对象超出范围时,lambda/closures如何处理引用,可能是UB。@FredOverflow:我的理解是,
std::function
不是一个简单的对象,尤其是在包装lambda时。引用它可能更好,以避免不必要的copying.如果lambda通过值捕获堆栈,则lambda可以超过这些变量,并将继续保留它们的副本。如果它通过引用捕获,则会出现问题。我们必须在函数内部复制它,因此复制它没有意义,因为它是传入的。您不需要funValid:,只需说
If(!theFunction)