mrm_dev
(mrm_dev)
November 21, 2024, 6:54pm
1
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
silnarm
(silnarm)
November 22, 2024, 4:26am
3
Simpler solution since an FDelegateHandle is just an int, drop the &
and pass by value.
mrm_dev
(mrm_dev)
November 22, 2024, 4:31am
4
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
mrm_dev
(mrm_dev)
November 22, 2024, 4:53am
5
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 ?
silnarm
(silnarm)
November 22, 2024, 4:55am
6
Indeed, my bad. DelegateHandle
has not been initialised at the point it is passed, so a reference or pointer will be required.
mrm_dev
(mrm_dev)
November 22, 2024, 6:45am
7
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, [](){
...
})