Home > front end >  A Problem with Recursive Void Lambda Expressions in C
A Problem with Recursive Void Lambda Expressions in C

Time:10-13

I would like to implement recursive void lambda expressions inside a function. I have created the C snippet below to illustrate my problem. Lambda is the recursive void lambda expression I would like to build inside Func1. However, when I compile with g , I run into the following compiler errors:

Lambda_void.cpp: In function ‘void Func1(std::vector<int>&)’:
Lambda_void.cpp:6:10: error: variable or field ‘Lambda’ declared void
     void Lambda = [](std::vector<int> &A)
          ^~~~~~
Lambda_void.cpp: In lambda function:
Lambda_void.cpp:11:13: error: ‘Lambda’ was not declared in this scope
             Lambda(A);
             ^~~~~~
Lambda_void.cpp:11:13: note: suggested alternative: ‘__lambda0’
             Lambda(A);
             ^~~~~~
             __lambda0
Lambda_void.cpp: In function ‘void Func1(std::vector<int>&)’:
Lambda_void.cpp:14:5: error: ‘Lambda’ was not declared in this scope
     Lambda(A);
     ^~~~~~

Changing to the lambda variable declaration from void to auto does not solve anything as the compiler has not identified the variable type before the first recursion. Are there any possible workarounds here? And why doesn't g allow to do this?

#include <iostream>
#include <vector>

void Func1(std::vector<int> &A)
{
    void Lambda = [](std::vector<int> &A)
    {
        while (A.size() < 5)
        {
            A.push_back(1);
            Lambda(A);
        }
    };
    Lambda(A);
}

int main()
{
    std::vector<int> C;
    Func1(C);
    for (auto& i : C) {std::cout << i << " ";}
    std::cout << std::endl;
    return 0;
}

CodePudding user response:

Since the internal lambda has not yet been instantiated, you cannot deduce its return type. One of the workarounds is to pass the lambda itself as a parameter (Godbolt):

auto Lambda = [](std::vector<int> &A, auto self) -> void
{
    while (A.size() < 5)
    {
        A.push_back(1);
        self(A, self);
    }
};
Lambda(A, Lambda);

But this is obviously very redundant, so the better way is to just use the free function for the recursion.

CodePudding user response:

See this question for recursive lamda-functions explanation. You can declare your Lambda as std::function<void(std::vector<int>&)> and capture it inside lambda:

std::function<void(std::vector<int>&)> Lambda;
Lambda = [&Lambda](std::vector<int>& A) {
    while (A.size() < 5) {
        A.push_back(1);
        Lambda(A);
    }
};
Lambda(A);

CodePudding user response:

void doesn't work as the type of a lambda isn't void.

Convert the lambda to a std::function and capture a reference to that:

#include <iostream>
#include <vector>
#include <functional>

void Func1(std::vector<int> &A)
{
    std::function<void(std::vector<int>&)> Lambda = [&](std::vector<int> &A)
    {
        while (A.size() < 5)
        {
            A.push_back(1);
            Lambda(A);
        }
    };
    Lambda(A);
}

int main()
{
    std::vector<int> C;
    Func1(C);
    for (auto& i : C) {std::cout << i << " ";}
    std::cout << std::endl;
    return 0;
}
  • Related