Creating a onetime lambda function bind to a delegate

How do I bind a lambda function such that it get’s invoked ONLY once and then unbinds?

I tried this but it doesn’t work:


DECLARE_MULTICAST_DELEGATE(FMyDelegate);

FMyDelegate MyDelegate;

FDelegateHandle DelegateHandle;
DelegateHandle=MyDelegate.AddLambda([this, &DelegateHandle](){

    ...

    bool WasRemoved = MyDelegate.Remove(DelegateHandle); // returns false
});

I something like this possible / feasible or should I look into something else entirely?

You’d have to make the delegate handle a member of ‘this’ instead of a local variable.

You’re capturing a reference to stack data, and when that variable goes out of scope then the reference in your lambda will be invalid.

You may also be able to do a TSharedPtr as a local variable and capture that (by value). Because then the handle won’t go out of scope when the function ends.

2 Likes

Simpler solution since an FDelegateHandle is just an int, drop the & and pass by value.

Nope that does not work I tried it, However @MagForceSeven 's answer works when making the delegate handle a member instead of using a local variable

though I’m trying to figure out how to use TSharedPtr so I can use it as a local variable

making the delegate handle a member works but Im trying to keep my code clean and use a local variable instead

I tried your TSharedPtr solution like this:

	TSharedPtr<FDelegateHandle> DelegateHandle = MakeShared<FDelegateHandle>();

	*DelegateHandle=MyDelegate.AddLambda([this, DelegateHandle](){

		bool WasRemoved = MyDelegate.Remove(*DelegateHandle); // returns true
	});

But I’m fairly new to TSharedPtr Will this cause any memory leaks? Also are there any edge cases where this might not work ?

Indeed, my bad. DelegateHandle has not been initialised at the point it is passed, so a reference or pointer will be required.

Also is this the right way to create a static function to bind it ?

template <typename DelegateType, typename FunctionType>
static void OnetimeMulticastDelegate(DelegateType &Delegate, FunctionType &&Lambda ){

	TSharedPtr<FDelegateHandle> DelegateHandle = MakeShared<FDelegateHandle>();
    
    *DelegateHandle = Delegate.AddLambda([DelegateHandle, &Delegate, Lambda]()
    {
        Lambda();
        
        if (DelegateHandle.IsValid())
             Delegate.Remove(*DelegateHandle);
    });
}


// usage
OnetimeMulticastDelegate(MyDelegate, [](){
   ...
})