On 02/06/2017 01:06, Gavin Lambert via Boost wrote:
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.
That was intentional. I in fact strongly toyed with attempt to access empty being an immediate std::terminate(), but I decided that throwing a special unique exception type would cause std::terminate() anyway in noexcept code, whilst in exception throwing land it was probably better not the arbitrarily exit the process. I could be very easily persuaded to put it back to std::terminate though.
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.
The programmer can always override the default handling of empty, value, error, exception. This is by design.
Why not just have exception() return the empty-state exception that value() would have thrown?
Hopefully now explained above. Would you prefer a std::terminate on accessing empty instead? I'm strongly leaning towards that now we'll have split empty-capable vs non-empty-capable types, indeed I just logged that to https://github.com/ned14/boost.outcome/issues/54. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/