Home > OS >  create a closure for a lambda in c
create a closure for a lambda in c

Time:02-26

is this the correct way to create a closure for a lambda function

#include <functional>
#include <memory>
#include <string>
#include <iostream>
  
using namespace std;


class A
{
    function<void()> fn(string str){    // (2)
        struct closure {
            int num;
        };
        auto ptr    = make_shared<closure>();
        ptr->num    = 99;

        auto fn     = [=](){
            ptr->num  ;
            cout << ptr->num << "  --  " << str << endl;
        };//fn
        return fn;
    }//fn
};//A
  
A a;

int main(){
    auto fn   = a.fn("1");

    fn();
    fn();
        
    auto fn2    = a.fn("2");
        
    fn2();
    fn2();
}//main

view code -> online c compiler

the arguments to the function that creates the lambda @(2) dont seem to be needed within the closure, is this actually true?

what are the caveats to using this approach, heap/stack = creme fraiche, do i need to release the memory?

what practical difference would it make to capture by reference within the lambda?

edit

maybe i over simplified, sometimes the function looks like this

  class A {
  
        void fn(string str){
        
              struct closure {
                    int num;
                    int token;
              };
              auto ptr    = make_shared<closure>();
              
              ptr->num    = 100;
              
              auto fn     = [=](){
              
                    ptr->num  ;

                    cout << str << ptr->num << endl;
                    
                    if(ptr->num==105){
                          list.rem(ptr->token);  // <= defined elsewhere
                    }
                    
              };
              
              ptr->token    = list.add(fn); // <= defined elsewhere
        
        }//fn
        
  };//A

CodePudding user response:

is this the correct way to create a closure for a lambda function?

Your lambda can be simplified to:

function<void()> fn(string str){
    return [str, i = 99]() mutable {
          i;
        std::cout << i << "  --  " << str << std::endl;
    };
}

do I need to release the memory?

You capture a std::shared_ptr by value, it would release its memory on destruction, you are fine.

what practical difference would it make to capture by reference within the lambda?

As you capture local variable, capturing by reference would lead to dangling pointer.

CodePudding user response:

It looks like it isn't wrong, but for what it is also looks like massive overkill.

You could accomplish the same thing without using sharerd_ptr or any dynamic memory, by simply capturing an int and making the lambda mutable:

std::function<void()> fn(std::string str){    // (2)
    return [=, num = 99]() mutable {
        num  ;
        std::cout << num << "  --  " << str << "\n";
    };
}

If you plan to copy your lambda and have both copies affect the same underlying data, OR, you hold onto that shared pointer and do more things with it, possibly after returning the lambda, then perhaps your approach makes more sense. A custom struct and shared ptr is heavy and I prefer simple whenever possible.

Also, the by-value / by-reference question is important, since str is printed out in the lambda, it needs to be sure that the object it uses continues to live. Since it is a function parameter, the argument will be destroyed when the function returns, so the lambda must not store a reference to it, or it'll be to a destructed object and cause undefined behavior if it's called. You need the copy to preserve the string so it's guaranteed to be valid when the lambda is called.

  • Related