如何使用 typedef 声明 lambda 函数,然后通过传递给函数来使用它?

Der*_*our 6 c++ parameters lambda

我现在正在学习 C++,对 Lambda 函数的语法非常困惑

我想在单元顶部定义 lambda,例如

   typedef const std::function<void (bool)> bitloop;
Run Code Online (Sandbox Code Playgroud)

或者

   typedef void bitloop(bool bit, int idx);
Run Code Online (Sandbox Code Playgroud)

稍后,将 lambda 接受到类中的函数中,例如,在我的 Bits 类中,有一个 forEach 方法

void forEach(const bitloop loop){
 for (int i = 0; i<=fCount-1;i++){
    loop(this->isSet(i),i);  
  }   
}
Run Code Online (Sandbox Code Playgroud)

然后最终能够稍后编写不同的循环函数,传递一个值和循环索引,以便我可以捕获本地范围内的变量,例如

bits.forEach([&](bool on, int i){ 
      output("index" + to_string(count));   //count is locally declared variable
  });
Run Code Online (Sandbox Code Playgroud)

如果我删除 &,它可以与第二种类型 def 一起正常工作,但是我无法捕获计数变量。

有人可以解释一下我的做法哪里出了问题,以及这是否是一种有效的方法?

小智 7

首先,您的第二个typedef实际上是正确的,但您第一个的签名typedef不正确。这就是我声明std::function 的方式:

// T1 : function object
typedef std::function<void(bool, int)> T1;

// T2 : pointer to function
typedef void (*T2)(bool, int);
Run Code Online (Sandbox Code Playgroud)

正如您已经观察到的,捕获局部变量的 lambda 函数当前不能用作函数参数T2请参阅本页上的注释)。下面显示的代码突出显示了此问题并重现了编译器错误。

struct Bits
{
  void forEach(const T2 &loop)
  {
    //...
  }
};

int main(int argc, char** argv)
{
  int i = 0; // local variable
  auto function1 = [](bool, int){ /**/ };
  auto function2 = [&i](bool, int){ /**/ };
  Bits bits;
  bits.forEach(function1); // OK
  //// if you uncomment the next line, the compiler would generate the following error
  //// [Error] no matching function for call to 'Bits::forEach(main(int, char**)::<lambda(bool, int)>)'
  //bits.forEach(function2);
Run Code Online (Sandbox Code Playgroud)

然而,捕获局部变量的 lambda 函数可以完美地用作T1.

struct Bits
{
  void forEach(const T1 &loop)
  {
    //...
  }
};

int main(int argc, char** argv)
{
  int i = 0; // local variable
  Bits bits;
  auto function1 = [](bool, int){ /**/ };
  auto function2 = [&i](bool, int){ /**/ };
  bits.forEach(function1); // OK
  bits.forEach(function2); // OK
Run Code Online (Sandbox Code Playgroud)

其次,还有另一种方法可以使用 lambda 作为函数参数,而无需显式声明std::function或函数类型……没错,它涉及到函数模板的使用。

struct Bits
{
  template<typename T3> void forEach(const T3 &loop)
  {
    //...
  }
};

int main(int argc, char** argv)
{
  int i = 0; // local variable
  Bits bits;
  auto function1 = [](bool, int){ /**/ };
  auto function2 = [&i](bool, int){ /**/ };
  std::function<void(bool, int)> function3 =  = [&i](bool, int){ /**/ };
  bits.forEach(function1); // OK
  bits.forEach(function2); // OK
  bits.forEach(function3); // OK
  bits.forEach([&i](bool, int){ /**/ }); // OK
Run Code Online (Sandbox Code Playgroud)

而且你也是对的,这就是如何定义一个捕获所有局部变量的 lambda 函数

int i = 0; // local variable
Bits bits;
bits.forEach([&](bool, int){ /**/ }); // OK
Run Code Online (Sandbox Code Playgroud)

有关其他 lambda 捕获选项,请参阅cppreference