Почему рекурсивные лямбда-функции выдают ошибку при использовании с auto? - PullRequest
0 голосов
/ 05 апреля 2020

Я пытаюсь использовать рекурсивные лямбда-функции с ключевым словом auto, как показано ниже.

#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'.

Я прошел ниже вопросы переполнения стека.

Ответы [ 2 ]

1 голос
/ 05 апреля 2020

Проблема не в типе возврата лямбда-выражения. Проблема заключается в типе самой лямбды.

Каждое лямбда-выражение является уникальным анонимным типом.

В вашем коде компилятор знает, что лямбда возвращает void, но пока нет знать тип лямбды, так как он еще не полностью ее проанализировал.

Чтобы дать контрпример для выделения проблемы.

#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
}
0 голосов
/ 05 апреля 2020

Вы не можете сделать лямбду рекурсивной. Лямбды не могут быть рекурсивными, потому что у них нет имени. Смотрите это: https://en.cppreference.com/w/cpp/language/lambda

безымянный функциональный объект, способный захватывать переменные в области видимости.

Здесь лямбда-генерирует перед инициализацией, таким образом, компилятор выдает ошибку.

Единственный способ реализовать ее в реальном лямбда-исчислении - использовать Y комбинатор . Но я думаю, что это бессмысленно в C ++. Тем более, что здесь вы вообще не используете enclosure.

В C ++ есть еще один способ его реализации: используйте std::function для замены auto, а затем вместо * введите lambda вместо * lambda.

...