Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested lambda function

Tags:

c++

c++11

lambda

I have the following code:

auto get_functor = [&](const bool check) {
    return  [&](const foo& sr)->std::string {
        if(check){
            return "some string";
        }
        return "another string"
    };
};
run(get_functor(true));

The run function signature:

void run(std::function<std::string(const foo&)> func);

I am getting the following error which is not so clear for me:

error C2440: 'return' : cannot convert from 'main::<lambda_6dfbb1b8dd2e41e1b6346f813f9f01b5>::()::<lambda_59843813fe4576d583c9b2877d7a35a7>' to 'std::string (__cdecl *)(const foo &)'

P.S. I am on MSVS 2013

Edit:

if I edit the code by replacing auto with the real type:

std::function<std::string(const foo&)> get_functor1 = [&](const bool check) {
    return  [&](const foo& sr)->std::string {
        if (check) {
            return "some string";
        }
        return "another string";
    };
};
run(get_functor1(true));

I am getting another error:

error C2664: 'std::string std::_Func_class<_Ret,const foo &>::operator
()(const foo &) const' : cannot convert argument 1 from 'bool' to
'const foo &'

Which is totally messed up!

like image 987
Humam Helfawi Avatar asked Apr 24 '17 06:04

Humam Helfawi


People also ask

Can you nest lambda functions?

Python allows lambda nesting, i.e., you can create another lambda function inside a pre-existing lambda function. For nesting lambdas, you will need to define two lambda functions – an outer and an inner lambda function. When the outer lambda is called, the inner lambda creates a function.

Can lambda functions have multiple lines?

No, you cannot write multiple lines lambda in Python. The lambda functions can have only one expression.

Can one lambda function have multiple triggers?

Your function can have multiple triggers. Each trigger acts as a client invoking your function independently. Each event that Lambda passes to your function has data from only one client or trigger.

Can lambda take multiple arguments?

As defined, a Lambda Calculus function can only take one argument. However, the effect of allowing multiple arguments to a function can be obtained using “currying”. A 2-parameter function is simulated with two 1-parameter functions. The result of applying the first function is another function.


1 Answers

I was able to reproduce the same error on VS 2013 with the following MVCE:

#include <iostream>
#include <functional>
#include <string>

struct foo {};

std::string run(std::function<std::string(foo const&)> f) {
    return f(foo());
}

int main() {

    auto get_functor = [&](bool const check) {
        return [=](foo const&) -> std::string { // Line of the compiler error
            if (check) {
                return "CHECK!";
            }
            else {
                return "NOT CHECK!";
            }
        };
    };

    std::cout << run(std::function<std::string(foo const&)>(get_functor(true)));
    return 0;
}

I then get the error:

Error   1   error C2440: 'return' : cannot convert from 'main::<lambda_1bc0a1ec72ce6dc00f36e05599609bf6>::()::<lambda_4e0981efe0d720bad902313b44329b79>' to 'std::string (__cdecl *)(const foo &)'

The problem lies with MSVC's inability to handle returned lambdas: when you do not specify the return type, it is trying to decay it into a regular function pointer. This fails because your lambda does capture elements!

Moreover, your fix is wrong since std::function<std::string(foo const&)> is not the type of get_functor but rather the type you want to return from it.

Forcing the embedding into an std::function of the returned lambda directly in get_functor will resolve your issue:

auto get_functor = [&](bool const check) -> std::function<std::string(foo const&)> {
    return [=](foo const&) -> std::string {
        if (check) {
            return "some string";
        } else {
            return "another string";
        }
    };
};
std::cout << run(get_functor(true));
like image 160
Rerito Avatar answered Sep 30 '22 17:09

Rerito