【问题标题】:how do you declare a lambda function using typedef and then use it by passing to a function?如何使用 typedef 声明 lambda 函数,然后通过传递给函数来使用它?
【发布时间】:2019-11-29 22:27:57
【问题描述】:

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

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

   typedef const std::function<void (bool)> bitloop;

   typedef void bitloop(bool bit, int idx);

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

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

然后终于可以在以后编写不同的循环函数,传递一个值和循环索引,这样我就可以在局部范围内捕获变量,例如

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

如果我删除 &,它适用于第二种类型 def,但我无法捕获计数变量。

有人可以解释我在哪里出错了,如果这是一种有效的方法?

【问题讨论】:

  • “解释我哪里出错了” 出了什么问题?任何编译器错误?你能写一个minimal reproducible example 并逐字发布错误吗?
  • 我不太明白这个问题。 Lambda 可以转换为 std::function 或传递给模板函数。如果可能的话,后者通常是更好的选择,
  • 副本如何回答问题?? @1201ProgramAlarm
  • 据我所知,您只是缺少函数签名的第二个参数:std::function&lt;void (bool)&gt; -> std::function&lt;void (bool, int)&gt;。函数类型 typedef 的第二种方法不起作用,因为带有捕获的 lambdas 不会衰减到函数指针。请注意,这两个 typedef 都不是 lambda 类型。每个 lambda 都有自己独特的类型。
  • @DerekSeymour 您需要逐字发布您在问题中收到的任何错误消息以及产生该错误消息的minimal reproducible example。 (点击edit这样做)

标签: c++ lambda parameters


【解决方案1】:

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

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

// T2 : pointer to function
typedef void (*T2)(bool, int);

正如您已经观察到的那样,捕获局部变量的 lambda 函数目前不能作为带有T2函数参数(请参阅此页面上的 cmets)。下面显示的代码突出显示了此问题并重现了编译器错误。

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

捕获局部变量的 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

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

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

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

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

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

【讨论】:

  • 实际上,我只是在我的编译器上测试了它,无论有没有&amp;,它在全局范围内都有相同的行为。但它似乎在函数范围内是必需的。
  • 是的,这就是“局部变量”通常所指的。全局变量的捕获行为不同。
  • @DerekSeymour 总是需要使用std::function。然而,通常最好使用模板方法,因为std::function 方法通常具有显着的运行时开销。那么#include&lt;functional&gt; 就不需要了。
  • @josh7115 函数指针的 typedef 可以直接完成:typedef void (*T2)(bool, int);using 关键字(自 C++11 起)也是定义类型别名的更清晰的替代方法:using T2 = void(*)(bool, int);。 OP 的 typedef 也没有错。您可以 typedef 函数的类型,而不是函数指针。这就是 OP 正确的做法。如果将函数类型用作函数参数,则将其解释为相应的函数指针类型(类似于函数参数中的int[]int*)。
  • typedef (*T2)(bool, int); -> typedef void (*T2)(bool, int);
猜你喜欢
  • 2020-05-03
  • 1970-01-01
  • 2016-06-30
  • 2019-09-27
  • 2021-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多