Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 Lambda Functions inside member methods inherit scope

I've written a function foreach that accepts a lambda function ala:

void foreach(void (*p)(pNode))
{ /* ... */ }

Which works as intended if I pass a lambda function from the main loop:

int a = 5;
env.N().foreach
(
    [&](pNode n)->void
    {
        n->tps(a); 
    }
);

However, if I try to call the same function from within a member method, the lambda function "inherits" the scope of the member function and generates a compiler error. For example, if I try to include it inside the member method of class Object named method(), I get the following error:

error: no matching function for call to ‘IDSet<Node>::foreach(Object::method()::<lambda(pNode)>)’
note: candidate is: void IDSet<T>::foreach(void (*)(IDSet<T>::pT)) [with T = Node, IDSet<T>::pT = pNode]

I realize this is the compiler being safe, since I could include instance-specific variables inside the lambda function, in which case the lambda would need to be scoped, however I'm wondering if it's possible to make this lambda "static".

I've tried a reinterpret_cast, however that gives me this error:

error: invalid cast from type ‘Object::method()::<lambda(pNode)>’ to type ‘void (*)(pNode)’

Specifying static before [&](pNode ... doesn't seem like valid syntax either.

Desperately, I also tried changing [&] to [=], [], [a], none of which worked.

Does anyone know if there is a way to do accomplish my goal of creating a "static" lambda function, or at any sort of lambda function that will be accepted for that matter?

Thanks!


Answer:

With help from Cat Plus Plus, I was able to turn my incorrect code:

void foreach(void (*p)(pT))
{
    for(pTiter i = _map.begin(); i != _map.end(); i++)
    {
        (*p)(i->second);
    }
}

into fully functional code:

void foreach(std::function<void(pT)>(p))
{
    for(pTiter i = _map.begin(); i != _map.end(); i++)
    {
        p(i->second);
    }
}

that does what I was looking for perfectly.

like image 764
jedwards Avatar asked Jun 13 '11 22:06

jedwards


People also ask

Do lambdas go out of scope?

A lambda object must not outlive any of its reference captured objects. Lambda expressions may capture objects with automatic storage duration from the set of enclosing scopes (called the reaching scope) for use in the lambda's function body.

What is the scope of a lambda function C++?

The context of a lambda is the set of objects that are in scope when the lambda is called. The context objects may be captured then used as part of the lambda's processing. Capturing an object by name makes a lambda-local copy of the object. Capturing an object by reference allows the lambda to manipulate its context.

What is the correct syntax for lambda expression in C++11?

Lambdas can both capture variables and accept input parameters. A parameter list (lambda declarator in the Standard syntax) is optional and in most aspects resembles the parameter list for a function. auto y = [] (int first, int second) { return first + second; };

Can a lambda closure be used to create a C++11 thread?

Can you create a C++11 thread with a lambda closure that takes a bunch of arguments? Yes – just like the previous case, you can pass the arguments needed by the lambda closure to the thread constructor.


1 Answers

Well, you can not use pointers.

void foreach(std::function<void(pNode)>);
like image 120
Cat Plus Plus Avatar answered Sep 18 '22 20:09

Cat Plus Plus