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.
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). 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. outcome<> is used almost exclusively within the sea; result<> only rarely (for cases where an exception cannot occur). 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.