std::optional<T> f() {
try { return it(); }
catch(...) {
clean_up();
return {};
}
}
Trivial. If you don't want to throw away the exception: T f() {
try { return it(); }
catch(...) {
clean_up();
throw;
}
}
But of course cleanup code belongs in a destructor, so nobody does that. In C++, we say T f() { return it(); }
and the responsible destructor does its job, either way.The try! macro didn't have that insight, and the first attempt to make a Try operator didn't either, but the current one does. This sort of experimentation is not available in practice to C++ but that would only slow it down a little, what prevents forward motion far more is that WG21 doesn't want to learn from other people's experiments.
C++ 23 gets std::expected which is, modulo IFNDR nonsense, a Result type. But C++ 23 doesn't have, and none of the further papers propose, a type analogous to ControlFlow.
I actually wondered how C++ 23 does the equivalent of Iterator::try_fold without ControlFlow, how do they express this idea? Did they use std::expected here as once Rust used Result ? The answer seems to just be "They don't" which I think gets to the heart of it.
A resumable, short-circuiting fold would be just as useful in C++ as it is in Rust, but it's easy to express nicely in Rust and doing so in C++ would insight anger from Exceptions purists, so that likely won't happen.