On 2/06/2017 06:33, Niall Douglas wrote:
On 01/06/2017 00:35, Gavin Lambert 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.
But it means that in a noexcept method, it's unsafe to call exception() without a try-catch, even though it would be safe to call in any case other than empty. And it means that exception() doesn't return the exception that would be thrown by value() in that case either. Maybe the answer is "so check for empty first!" but that seems like clutter if you're not expecting to see empty but still need to put it in to defensively avoid a std::terminate. And it's bizarre to have empty have super-throw behaviour if the method wants to treat it like an optional success value, as you've suggested is occasionally useful. Why not just have exception() return the empty-state exception that value() would have thrown?
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.
It's legal; you just need to explicitly declare it as noexcept(false) and only throw the exception if (!std::uncaught_exception()). Though people will probably still yell at you about it. That sort of policy can sometimes bite you with copyable types, though. Sure, you could mark the source of a copy as "handled", but you don't really know which one is going to be kept.