【问题标题】:Why recursive lambda functions are throwing error when used with auto?为什么递归 lambda 函数与 auto 一起使用时会抛出错误?
【发布时间】:2020-04-05 09:05:18
【问题描述】:

我正在尝试使用带有 auto 关键字的递归 lambda 函数,如下所示。

#include <iostream>

using namespace std;

int main()
{
    auto func = []()->void{
        static int x = 0;
        cout << x << endl;
        if (x < 5) {
            func();
            x++;
        }
    };

    func();
    return 0;
}

但它抛出编译器错误如下。

main.cpp: In lambda function:
main.cpp:19:13: error: use of ‘func’ before deduction of ‘auto’
             func();
             ^~~~

我知道我们可以使用 std::function 实现相同的效果。但我想知道为什么使用“auto”会出错。

我经历了下面的堆栈溢出问题。

但我无法弄清楚为什么在这种情况下使用 lambda 的 auto 会引发错误。谁能告诉我为什么会出现这个错误?

【问题讨论】:

  • 错误信息不是很清楚吗? auto 在初始化的右侧被处理之前确定。
  • @JasperKent:我通过错误消息理解了这一点。但我已经明确使用“void”作为返回类型。那为什么编译器无法确定这里是什么。
  • 顺便说一句:如果 lambda 定义并传递给 var,那么它没有捕获任何东西有什么意义。在这种情况下,每个“正常”功能都更适合。我在这个例子中看到的是对 lambda 的滥用。 lambda 作为给定算法的临时函数对象参数非常好。但是滥用它作为一个正常的功能只会降低代码的可读性。我的意见:-)
  • @kadina 正如我所说,因为它必须评估整个右侧
  • @Klaus:我知道在这种情况下它没有多大意义 :) 我只是想了解为什么这不起作用。所以没用capture,写了个简单的。

标签: c++11 c++14


【解决方案1】:

问题不在于 lambda 表达式的返回类型。问题在于 lambda 本身的类型。

每个 lambda 表达式都是唯一的匿名类型。

在您的代码中,编译器知道 lambda 返回 void,但它还不知道 lambda 的类型,因为它还没有完全解析它。

举一个反例来突出这个问题。

#include <iostream>

int main()
{
    int x;
    auto func = [&](){
        // func is going to become an int here, but the compiler does not know that yet
        // it has to parse the whole expression first.
        x = func;
        return 5;
    }(); // <-- calling the lambda and assigning the return value to func
}

【讨论】:

    【解决方案2】:

    你不能让 lambda 递归。 Lambda 不能递归,因为它们没有名称。看到这个:https://en.cppreference.com/w/cpp/language/lambda

    一个未命名的函数对象,能够捕获范围内的变量。

    这里 lambda 在初始化之前生成,因此编译器会给你一个错误。

    在真正的 lambda 演算中实现它的唯一方法是使用 Y combinator。但我认为这在 C++ 中毫无意义。尤其是在这里,您根本没有使用外壳。

    在 C++ 中,还有另一种实现方式:使用 std::function 替换 auto,然后调用 std::function 而不是 lambda。

    【讨论】:

    • '因为他们没有名字。'??? lambda 有一个名字。这是func
    • @JasperKent 这不是 lambda 的名字。 Lambda 是匿名函数(实际上是 C++ 中的函子)
    • 我认为您的意思是“命名类型”
    • @JasperKent 我不确定你是什么意思,lambdas 和它们的类型都是匿名的。
    猜你喜欢
    • 2019-07-11
    • 1970-01-01
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    相关资源
    最近更新 更多