On 01/06/2017 00:35, Gavin Lambert via Boost wrote:
On 1/06/2017 08:17, Niall Douglas wrote:
The programmer, when working with outcome<T>, knows that calling .exception() will return the exact same exception as would be thrown when calling .value(), thus saving wrapping .value() in a try...catch just to capture the exception_ptr emitted.
Except empty. value() throws that as an exception. exception() also throws that as an exception (not returning it), which means that the programmer can't make that assumption you just claimed.
Maybe that's what you want (as it leads very quickly to empty == std::terminate), but it's not consistent with use of empty as a success return as you've suggested in a few places.
Empty is supposed to have the severest, most abnormal default actions.
For result<T>, it's basically a castrated outcome<T> used only for performance sensitive code, or rather, to say "this function takes performance very seriously".
From the docs and discussion thus far, this is not the impression I had.
The impression I had was that result<T> should be used everywhere in inner exception-enabled code by preference (since exceptions should not be caught, they should be propagated outwards).
That's one approach. But definitely not the sole one. result<T> may also be returned from any function which solely calls STL exception throwing code. Indeed, Outcome provides a catch-to-result macro just for that. This lets you call STL code easily from within noexcept-land.
And then up at the entrypoint from the sea of noexcept to the exception-enabled island, that entrypoint (which is itself noexcept) should return an outcome<> from the result<> of its children or an internal try-catch to propagate out an exception_ptr.
This part is often the case.
outcome<> is used almost exclusively within the sea; result<> only rarely (for cases where an exception cannot occur).
Not necessarily. In my own code to date, I've mostly used outcome<> in exception throwing land and result<> in noexcept-land. But you're right that in most code bases, you probably would use outcome<T> for that yes.
Further up the call stack (back in exception-throwing land) you receive an outcome<> and immediately unpack and rethrow any exception, or otherwise go back to returning result<>s.
Yes, but don't forget result<T>.value() throws the exact same exception as outcome<T>(result<T>).value(). Certainly when using AFIO v2, I find myself writing a lot of afio_function().value();. I really wish it were more permissible to throw from destructors, then if the return were errored and you don't deal with it, it throws, no .value() needed. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/