Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing and storing lambda function as callbacks

Tags:

I was wondering if this would be an accepted approach to writing callbacks:

Storing callbacks:

struct EventHolder {     std::function<void()> Callback;     EventTypes::EventType Type; }; std::vector<Events::EventHolder> EventCallbacks; 

Method definition:

void On(EventType OnEventType,std::function<void()>&& Callback) {     Events::EventHolder NewEvent;     NewEvent.Callback=std::move(Callback);     NewEvent.Type=OnEventType;     EventCallbacks.push_back(std::move(NewEvent)); } 

Binding event:

Button->On(EventType::Click,[]{     // ... callback body }); 

My biggest question would be regarding passing the Callback by value. Is this a valid approach?

like image 221
Grapes Avatar asked Mar 27 '13 05:03

Grapes


People also ask

Is a lambda function a callback function?

Lambda function are anonymous functions. Callback can be named or anonymous. So all lambda functions can be a callback function but not all callback function can be lambda function.

What is callback in AWS Lambda?

The third argument, callback , is a function that you can call in non-async handlers to send a response. The callback function takes two arguments: an Error and a response. When you call it, Lambda waits for the event loop to be empty and then returns the response or error to the invoker.

Are lambdas always Inlined?

All lambdas are inline. Not all calls to them are necessarily inlined.

How do you define a callback function in C++?

In simple language, If a reference of a function is passed to another function as an argument to call it, then it will be called as a Callback function. In C, a callback function is a function that is called through a function pointer. In C++ STL, functors are also used for this purpose.


2 Answers

This is a perfectly valid approach to storing event handlers.

However, I would like to point out some details regarding the signature of your function for adding a callback. You worry about passing it by value vs by reference. In your example, you currently have:

void On(EventType OnEventType,std::function<void()>&& Callback) 

This is good, as long as you will only ever bind this to rvalues. However, unless there are particular reasons why you want to disallow it, I would recommend that you always have a method which accepts parameters by value or lvalue reference and add the rvalue reference version as a complement, if deemed necessary.

Not having a method which takes an lvalue reference means your code will currently fail to compile given this:

std::function<void()> func([](){/*something clever*/}); // Do something necessary with func, perhaps logging or debug prints. Button->On(EventType::Click, func); 

For simplicity, whenever you're choosing how to pass a value, you can simply follow these guidelines in general:

  • If you need a copy of or intend to modify the value sent in, without wanting to change the actual object passed: pass by value.
  • If you intend to modify the value sent in, and want these changes to affect the actual object passed: pass by reference.
  • If you do not want to change the object passed, but believe it is beneficial to avoid copying: pass by const reference.
  • If you take parameters by value, reference or const reference, and believe there are valuable optimizations which can be achieved using the knowledge that the input parameter is a temporary: also allow to pass by rvalue reference.
like image 175
Agentlien Avatar answered Oct 18 '22 17:10

Agentlien


Yes. Functions are either raw function pointers or light weight classes that their copy constructor has no side effect, so their copy must act as original object, so this approach is completely ok. But why you pass object by value and then move it to your original container, you can pass reference and then copy it to your container and have an overloaded function that accept an r-value reference (should not be so important).

like image 21
BigBoss Avatar answered Oct 18 '22 16:10

BigBoss