【问题标题】:Is it valid for a lambda to, essentially, close over itself?一个 lambda 从本质上来说,关闭自己是否有效?
【发布时间】:2012-01-25 13:46:59
【问题描述】:

这个 lambda 递归有效吗?

#include <functional>
#include <iostream>

int main() {
   std::function<int(int)> g = [&g](int k) {
       return (k ? k * g(k-1) : 1);
   };

   std::cout << g(10); // 3628800
}

它是appears to compile and run ok,但我很担心在我初始化它的同一个语句中关闭g。 1-10 的严格效度...?

【问题讨论】:

  • C++0x 示例 here 将其分成 2 个语句,但从未解释原因。
  • 好吧,g 已经在初始化程序之前声明了,我很确定引用已声明但未初始化的对象是有效的,在这种情况下这很好。我会看看能不能找到一些标准的来支持它。
  • @SLaks: 它也不会在 java 中编译,重点在哪里?
  • @AaronMcDaid:你正在尝试发明Y Combinator。函数式编程很有趣。
  • @Downvoter:那为什么?

标签: c++ lambda c++11


【解决方案1】:

在您通过引用捕获g 时,它已被声明,因此该名称可供使用:

3.3.2/1 名称的声明点紧接在其完整声明符之后(第 8 条)和其初始值设定项之前

您可以在初始化之前以有限的方式使用对象 - 基本上,任何不依赖于值的东西都可以:

3.8/6 在对象的生命周期开始之前但在对象将占用的存储之后 已分配[...]任何引用原始对象的glvalue都可以使用,但仅限于有限的 方法。 [...] 使用不依赖于其值的 glvalue 的属性是明确定义的。

所以根据我的理解,你所做的事情是明确定义的。

(尽管过于迂腐,我不认为它是在分配自动对象的存储时指定的,并且 8.3.2/5 说“应初始化引用以引用有效对象”而不定义“有效”,因此可以争论它的定义不明确)。

【讨论】:

  • 我同意绑定引用不需要左值到右值的转换,但是该领域的语言语义非常难以解释。 :( 即使是 C++!
  • 好的,我觉得这让我很满意!
  • 我正要发布这个:P 像任何函数定义一样,代码不会立即执行;从定义的角度来看,g 不需要值出于同样的原因 k 不需要值。 g[&amp;g] 一起使用,但这只是获取未来函数的地址。并且g 存在于此时,因为声明发生在赋值之前。
  • @user112358132134 虽然直觉上你可能是正确的,但你可能也看到我们正在这里进入严格的语言律师领域,不需要像指针那样实现引用并且实际工作的 UB仍然是 UB。
  • 值得指出的是,如果(通常建议用于 lambda)您将 fact 的类型声明为 auto,这将是不合法的:不能使用 auto 变量在它自己的初始化程序中。
猜你喜欢
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-08
  • 1970-01-01
相关资源
最近更新 更多