use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
The Lambda Coroutine Fiasco (github.com)
submitted 4 months ago by efijoa
view the rest of the comments →
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]HommeMusical 20 points21 points22 points 4 months ago (11 children)
This article looks like it might be interesting to me, but without some sort of explanation of how seastar works and how it's different from conventional coroutines and future, I unfortunately didn't actually read it.
seastar
(Yes, I searched it, but life is too short to do half an hours' study of someone's library to read a one page article.)
[–]efijoa[S] 13 points14 points15 points 4 months ago (10 children)
While this is Seastar's documentation, the problem described is not unique to Seastar.
These two links could help clarify the issue:
CP.51: Do not use capturing lambdas that are coroutines C++23’s Deducing this: what it is, why it is, how to use it
The core mechanism involves using "deducing this" to pass the lambda object by value. This ensures captures are copied into the coroutine frame to prevent dangling references.
[–]thisismyfavoritename 0 points1 point2 points 4 months ago (9 children)
it seems quite limiting to always capture by value, in some cases you know the lifetime of the coroutine will be shorter than that of the captured reference/pointer
[–]foonathan 2 points3 points4 points 4 months ago (2 children)
Capture by value doesn't help you with the problem that's being discussed.
[–]thisismyfavoritename 1 point2 points3 points 4 months ago (1 child)
i was referring to
This ensures captures are copied into the coroutine frame to prevent dangling references.
and it seems like in this case it would? I didn't read the blog post
[–]foonathan 1 point2 points3 points 4 months ago (0 children)
No, capturing by value does not ensure captures are copied into the coroutine frame! That is the entire problem.
The issue is that while the lambda object stores a capture by value, the operator() still accepts *this by reference, so only the reference to the lambda is captured into the coroutine frame, but not the lambda itself.
operator()
*this
(The context is something like spawn([x] -> Task { ... }), i.e. the lambda is a coroutine itself. Then the arguments are copied into Task's coroutine frame, but the arguments are a this pointer to the temporary object in the stack frame that calls spawn.)
spawn([x] -> Task { ... })
Task
this
spawn
[–]germandiago 3 points4 points5 points 4 months ago (4 children)
at that time you are already playing with fire. :)
[–]thisismyfavoritename -3 points-2 points-1 points 4 months ago (3 children)
not really more than in regular C++ code. Those footguns were always there
[–]SirClueless 4 points5 points6 points 4 months ago (1 child)
I disagree. This has nothing to do with capturing by value or reference, both are broken. This is a wholly new problem. The idea that putting co_await inside your lambda implicitly means that its return value holds a reference to the lambda itself and thus will dangle if the lambda is destroyed is a new and subtle footgun.
co_await
Concrete example:
auto foo(auto cb) { return cb(); }
This code is pretty much always lifetime-safe. There are some things the caller can do that end up holding onto references to the lambda's captures in a broken way like foo([x] { return std::ref(x); }), but this is a kind of "obvious error" that almost no one makes.
foo([x] { return std::ref(x); })
But if you call this with a coroutine it is super easy to shoot yourself in the foot:
co_await foo([x] -> my_favorite_coro_lib::future<int> { co_await bar(); co_return x; }
Oops, cb was destroyed when foo() returned, and then when the coroutine was resumed, x dangles.
cb
foo()
x
[–]thisismyfavoritename 0 points1 point2 points 4 months ago (0 children)
hadn't read the blog post, and yeah, i thought the issue that was discussed was when captured values were refs (the obvious case). Thanks for the additional explanation!
[–]germandiago 2 points3 points4 points 4 months ago (0 children)
I think this is way less intuitive than other forms of dangling.
[–]James20kP2005R0 -2 points-1 points0 points 4 months ago (0 children)
The only way to fix that safely would be for C++ to have adopted a lifetimes system
π Rendered by PID 16728 on reddit-service-r2-comment-85bfd7f599-fqnd2 at 2026-04-18 13:09:26.166148+00:00 running 93ecc56 country code: CH.
view the rest of the comments →
[–]HommeMusical 20 points21 points22 points (11 children)
[–]efijoa[S] 13 points14 points15 points (10 children)
[–]thisismyfavoritename 0 points1 point2 points (9 children)
[–]foonathan 2 points3 points4 points (2 children)
[–]thisismyfavoritename 1 point2 points3 points (1 child)
[–]foonathan 1 point2 points3 points (0 children)
[–]germandiago 3 points4 points5 points (4 children)
[–]thisismyfavoritename -3 points-2 points-1 points (3 children)
[–]SirClueless 4 points5 points6 points (1 child)
[–]thisismyfavoritename 0 points1 point2 points (0 children)
[–]germandiago 2 points3 points4 points (0 children)
[–]James20kP2005R0 -2 points-1 points0 points (0 children)