When integrating Asio with C++20 std::execution, the set_value operation must not throw exceptions, but Asio can deliver completion signatures that don't match the declared value categories, creating hidden throw sites during value conversions. The solution involves converting all Asio values to the appropriate types before calling set_value, catching any exceptions during conversion, and directing them through the receiver's error channel using set_error, while ensuring the converted values match the completion signature requirements.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Lightning Talk: Can `set_value` Actually Throw? - Robert Leahy - CppCon 2025Added:
I chose to go to CPCON because there's plenty of opportunities to both have a lot of fun and network. [music] You can come here to just learn and study and there's a great community behind it.
[applause] What if you wanted to integrate stood execution and AIO?
But Eric Nebler said the sender claims to send a particular set of completions, but in actual fact, it completes the result that is not one of the declared completion signatures. Let's dig into this compiler warning. Let's see what's actually going on. My operation claims that it sends an error code as an RV value, but actually sends it as a const LV value. Looking at the code I wrote to glue together stood execution in AIO, we see no problems. I'm perfectly forwarding through everything AO sends me. And so the issue is with AIO. It is sending values with value categories it did not claim. We could simply say this is AO's problem, but if you want to marry these two ecosystems, we need to deal with this. So first, let's figure out why this is even a problem worth diagnosing. Let's imagine we have a sender that accepts a stood string by value. We have an operation which declares it sends an RV value stood string. But then when we go ahead and complete the operation, we complete it with a const L value. To understand further what's going on here, let's decompose stood execution set value into what the standard says it actually does a member call on the receiver. But this isn't all that's going on here. Because in order to pass a const L value to a member function which accepts a parameter by value, we need to create a PR value. We need to copy the string.
And here in lies the issue because the standard not only defines the transformation stood execution set value performs, it also says that none of the operations it performs can throw an exception. But we don't even need to reach for this line of reasoning. We can go back to this receiver and we can say what if the author thereof simply decided it would accept an RV value reference. We can't bind const L values to an RV value reference. And so this wouldn't even compile. And so what we need to do is we need to take every single value we get from AIO and convert it appropriately. We have the top function which simply does nothing and passes the value through and we have the bottom function which performs the needful conversion. Or at least you might be hoodwinkedked into thinking that seeing the top one is annotated no except and the bottom one is not until I show you the static assert and tell you that it actually fires for this implementation. The implementation thinks that converting an alternated bite string to a stood string can't throw an exception. And the reason for that is because of the constraint on this function. It is erroneous because of course you can convert a null terminated by bite string to a stood string rv value reference. It will of course immediately dangle and that conversion can throw an exception despite what the function says. And so what we need to do is modify this constraint to add the type trade added to the standard for exactly this reason.
With that in mind, we can move on and we can write an imple function which performs our conversion on each and every argument before calling stood execution set value. But there's things we haven't seen the definition of on this slide. How do we actually get the ground truth of the types these things are supposed to be? Who's going and finding the completion signature that matches and feed feeding in those types?
And since stood execution operations can compete with multiple completion signatures, how do we even pick that completion signature? We're going to go ahead and we're going to abuse operator overloading to do this. We're going to go ahead and we're going to provide a non-specialized class that matches set error and set stop completion signatures because we don't care about them. Then we have a function call operator for every completion signature that sends set value t. We have a function call operator that accepts all those arguments and returns a stopup of those arguments so we can extract it from overload resolution. But in order to use overload resolution, we need an overload set. And so we form one of those by deriving from our base class for each and every one of our signatures. Now when we call the function call operator, it's going to perform overload resolution and tell us which completion signature it picked which requires of of course to use this functionality and so we write a set value helper. It goes off and it invokes our overload set in an unevaluated context and determines the matching completion signature. It then goes and feeds us into set value imple as the template parameter passes the receiver passes the appropriate index sequence and of course passes all those raw nasty unconverted values from AIO that we don't know correlate with any completion signature. Doing all this of course gives us absolutely nothing if we don't go back and visit that previously simple beautiful code we wrote and enrich it with our new understanding that we need to convert all of the arguments catch the exceptions and direct them down the error channel of the receiver. Now finally we have married stood execution and AIO together.
[applause]
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 viewsβ’2026-05-28
How agent o11y differs from traditional o11y β Phil Hetzel, Braintrust
aiDotEngineer
450 viewsβ’2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanationπ―β
LearnwithSahera
1K viewsβ’2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 viewsβ’2026-05-29
Search Algorithms Explained in 60 Seconds! π€π¨
samarthtuliofficial
218 viewsβ’2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 viewsβ’2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 viewsβ’2026-05-29
So What's Odin Lang Even Good For
TechOverTea
131 viewsβ’2026-06-01











