You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I think that 'deferred' is one of the best features in ETL, but it has a drawback that it can't handle lambda captures very well.
I've been tinkering around a solution to allow lambda captures that have the same size or less as void* for rvalue assigned delegates, i.e. the following example would be allowed:
MyObject o;
etl::delegate<void(void)> d { [&o](){ o.call(); } }; // lambda capture object will have same size as void*
d();
In the current implementation, this would lead to undefined behavior as the lambda capture would be out-of-scope when the call is performed but with my new implementation, this is perfectly fine.
Now to the problem with my implementation. It may behave inconsistently and/or break old implementations. Take the following example:
void func(etl::delegate<void(void)> d);
...
func([&o1, &o2](){ o1.set(o2); }); // compile error with my implementation
The above example is perfectly fine with the current implementation and contains no errors if the delegate is invoked within func(...)'s scope, but in my proposal, this would lead to a compile error because the lambda capture clause is larger than void*. I could choose to make a fallback to the old implementation, but that may become a surprise for the user when the delegate is used as a deferred callback, and no errors have been generated.
Another problem with my implementation is the following example:
In the above example, when the initialization is done via lvalue reference, I could choose to use SBO, but I chose to not do that as this would break the old implementation with functors. However, this wouldn't lead to any compile errors in the current implementation.
To solve my dilemmas, we could add similar functions as std:ref and std:cref to solve the problem. This would also make it more visible for the user of the delegate function that the object doesn't work as std::function when using it toghether with functors and lambdas. However, this would most likely break many implementations that use this function.
We could also add a new functionality called etl::deferred_delegate to visualize that the function will be called out of scope, but that would most likely be a duplication of the current delegate implementation.
Suggestions on how to solve this are appreciated, or should we ditch my idea with SBO captures, or should I make an MR as-is?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I think that 'deferred' is one of the best features in ETL, but it has a drawback that it can't handle lambda captures very well.
I've been tinkering around a solution to allow lambda captures that have the same size or less as
void*
for rvalue assigned delegates, i.e. the following example would be allowed:In the current implementation, this would lead to undefined behavior as the lambda capture would be out-of-scope when the call is performed but with my new implementation, this is perfectly fine.
Now to the problem with my implementation. It may behave inconsistently and/or break old implementations. Take the following example:
The above example is perfectly fine with the current implementation and contains no errors if the delegate is invoked within
func(...)
's scope, but in my proposal, this would lead to a compile error because the lambda capture clause is larger thanvoid*
. I could choose to make a fallback to the old implementation, but that may become a surprise for the user when the delegate is used as a deferred callback, and no errors have been generated.Another problem with my implementation is the following example:
In the above example, when the initialization is done via lvalue reference, I could choose to use SBO, but I chose to not do that as this would break the old implementation with functors. However, this wouldn't lead to any compile errors in the current implementation.
To solve my dilemmas, we could add similar functions as
std:ref
andstd:cref
to solve the problem. This would also make it more visible for the user of the delegate function that the object doesn't work asstd::function
when using it toghether with functors and lambdas. However, this would most likely break many implementations that use this function.We could also add a new functionality called
etl::deferred_delegate
to visualize that the function will be called out of scope, but that would most likely be a duplication of the current delegate implementation.Suggestions on how to solve this are appreciated, or should we ditch my idea with SBO captures, or should I make an MR as-is?
Here is the link to my take on how to implement the suggestion:
https://github.com/devjoa/etl/tree/feature/improve-delegate
Beta Was this translation helpful? Give feedback.
All reactions