C 11 中的递归 lambda 函数

新手上路,请多包涵

我是 C++11 的新手。我正在编写以下递归 lambda 函数,但它无法编译。

总和.cpp

 #include <iostream>
#include <functional>

auto term = [](int a)->int {
  return a*a;
};

auto next = [](int a)->int {
  return ++a;
};

auto sum = [term,next,&sum](int a, int b)mutable ->int {
  if(a>b)
    return 0;
  else
    return term(a) + sum(next(a),b);
};

int main(){
  std::cout<<sum(1,10)<<std::endl;
  return 0;
}

编译错误:

vimal@linux-718q:~/Study/09C++/c++0x/lambda> g++ -std=c++0x sum.cpp

sum.cpp: 在 lambda 函数中:sum.cpp:18:36: error: ‘ ((<lambda(int, int)>*)this)-><lambda(int, int)>::sum ’ 不能用作函数

gcc 版本

gcc 版本 4.5.0 20091231(实验性)(GCC)

但是,如果我更改 sum() 的声明,如下所示,它可以工作:

 std::function<int(int,int)> sum = [term,next,&sum](int a, int b)->int {
   if(a>b)
     return 0;
   else
     return term(a) + sum(next(a),b);
};

有人可以解释一下吗?

原文由 weima 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 925
2 个回答

想想 自动 版本和完全指定的类型版本之间的区别。 auto 关键字从它初始化的任何东西中推断出它的类型,但是你初始化它的东西需要知道它的类型是什么(在这种情况下,lambda 闭包需要知道它正在捕获的类型)。有点鸡和蛋的问题。

另一方面,完全指定的函数对象的类型不需要“知道”任何关于分配给它的内容,因此 lambda 的闭包同样可以完全了解其捕获的类型。

考虑一下对代码的这种轻微修改,它可能更有意义:

 std::function<int(int, int)> sum;

sum = [term, next, &sum](int a, int b) -> int {
    if (a > b)
        return 0;
    else
        return term(a) + sum(next(a), b);
};

显然,这不适用于 auto 。递归 lambda 函数工作得非常好(至少它们在 MSVC 中工作,我有使用它们的经验),只是它们与类型推断并不真正兼容。

原文由 I. M. McIntosh 发布,翻译遵循 CC BY-SA 4.0 许可协议

在 C++23 中推导 this ( P0847 ) 将被添加:

 auto f = [](this auto& self, int i) -> int
{
    return i > 0 ? self(i - 1) + i : 0;
}

目前它仅在 EDG eccp 中可用,并且(部分)在 MSVC 中可用:

https://godbolt.org/z/f3E3xT3fY

原文由 Yankes 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题