Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Enable Delegates to conveniently use stateful lambdas #1410

Merged

Conversation

benjaminhuth
Copy link
Member

This PR adds functionality to the Acts::Delegate, that enables to construct, assign and connect stateful lambdas like this:

int n = 0;
auto lambda = [&](){ ++n; };

Acts::Delegate<void()> d(lambda);
d = lambda;
d.connect(lambda);

The use of temporary stateful lambdas is forbidden due to deleted overloads with Callable &&:

Acts::Delegate<void()> d([&](){ ++n; }); // compile error

I havn't checked yet if this can simplify code somewhere in Core or Examples, but I ran in situations myself where this would be useful.

@benjaminhuth benjaminhuth added Component - Core Affects the Core module Improvement Changes to an existing feature labels Aug 9, 2022
@benjaminhuth benjaminhuth added this to the next milestone Aug 9, 2022
@codecov
Copy link

codecov bot commented Aug 9, 2022

Codecov Report

Merging #1410 (a8454f5) into main (ba1e563) will increase coverage by 0.02%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main    #1410      +/-   ##
==========================================
+ Coverage   47.76%   47.79%   +0.02%     
==========================================
  Files         380      380              
  Lines       20164    20173       +9     
  Branches     9387     9387              
==========================================
+ Hits         9632     9641       +9     
  Misses       4083     4083              
  Partials     6449     6449              
Impacted Files Coverage Δ
Core/include/Acts/Utilities/Delegate.hpp 83.87% <100.00%> (+6.59%) ⬆️

📣 Codecov can now indicate which changes are the most critical in Pull Requests. Learn more

Copy link
Member

@paulgessinger paulgessinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this just explicitly tries to grab the operator() function pointer for a lambda? Should be ok I think!

@asalzburger
Copy link
Contributor

@paulgessinger is this still waiting for the sentinel backlog?

@paulgessinger
Copy link
Member

Still working on fixing that, sorry. I'll override the merge here.

@paulgessinger paulgessinger merged commit f673126 into acts-project:main Aug 10, 2022
@paulgessinger paulgessinger added the backport develop/v19.x Backport this PR to the v19.x series label Aug 10, 2022
acts-project-service pushed a commit that referenced this pull request Aug 10, 2022
This PR adds functionality to the `Acts::Delegate`, that enables to construct, assign and connect stateful lambdas like this:

```c++
int n = 0;
auto lambda = [&](){ ++n; };

Acts::Delegate<void()> d(lambda);
d = lambda;
d.connect(lambda);
```

The use of temporary stateful lambdas is forbidden due to deleted overloads with `Callable &&`:
```c++
Acts::Delegate<void()> d([&](){ ++n; }); // compile error
```

I havn't checked yet if this can simplify code somewhere in Core or Examples, but I ran in situations myself where this would be useful.

(cherry picked from commit f673126)
kodiakhq bot pushed a commit that referenced this pull request Aug 10, 2022
…1410 to develop/v19.x] (#1414)

Backport f673126 from #1410.
---
This PR adds functionality to the `Acts::Delegate`, that enables to construct, assign and connect stateful lambdas like this:

```c++
int n = 0;
auto lambda = [&](){ ++n; };

Acts::Delegate<void()> d(lambda);
d = lambda;
d.connect(lambda);
```

The use of temporary stateful lambdas is forbidden due to deleted overloads with `Callable &&`:
```c++
Acts::Delegate<void()> d([&](){ ++n; }); // compile error
```

I havn't checked yet if this can simplify code somewhere in Core or Examples, but I ran in situations myself where this would be useful.
@paulgessinger paulgessinger modified the milestones: next, v20.0.0 Aug 16, 2022
@benjaminhuth benjaminhuth deleted the feature/delegate-lambdas branch September 13, 2022 14:40
@benjaminhuth benjaminhuth restored the feature/delegate-lambdas branch February 22, 2023 07:45
@benjaminhuth benjaminhuth deleted the feature/delegate-lambdas branch February 22, 2023 07:45
@timadye
Copy link
Contributor

timadye commented May 26, 2024

Can we document the additional functionality in this PR in the comments at the top. I saw the limitations listed there and used a complicated workaround, when I could have just used connect(lambda). Fortunately, I eventually noticed the comments further down.

@paulgessinger
Copy link
Member

Thinking about this again, I'm wondering if we should make this more explicit somehow, with a tag type to clearly mark what's going on.

I've seen some cases where this was (ab)used and it can be a bit of a footgun. We use the lvalue-ness to imply it's owned somewhere... but that's not clear to the user at all.

Thoughts?

@andiwand
Copy link
Contributor

ping @benjaminhuth

@timadye
Copy link
Contributor

timadye commented May 27, 2024

I assume the issue is that the delegate does not own the lambda - or is there something else I might be missing? My use has the lambda in the same scope as the extensions (and hence delegate), so this is good. It is made clear in the comments at the top of Delegate.h. I'm not sure what else one can do to protect the user.

@benjaminhuth
Copy link
Member Author

@paulgessinger I'm not 100% sure what you mean by "make it more explicit"?

Like Delegate(my_stateful_lambda, Acts::Stateful{}) resp my_delegate.connect(my_stateful_lambda, Acts::Stateful{})? And what kind of abuses you refer to?

So to me it seems like a good proposal to improve the documentation to showcase the construction/connection with stateful lambdas...

@paulgessinger
Copy link
Member

I've seen it being used to set a lambda and then not being aware that it immediately dangles when the lambda itself goes out of scope.

This can happen as well of course with member functions but it's less likely to do by mistake I'd say.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport develop/v19.x Backport this PR to the v19.x series Component - Core Affects the Core module Improvement Changes to an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants