On 31/05/2017 00:43, Gavin Lambert via Boost wrote:
On 31/05/2017 01:18, Niall Douglas wrote:
The current behaviour is "always throw on observing empty". That's what makes empty special (and it traps unintentional propagation of empty).
That makes sense when empty is always "you forgot to return a value". However you've said yourself that sometimes you've hijacked it as an intentional return of no value (as in optional<T>), and that's where things get murkier.
You do realise there is nothing stopping a person using the valued state to return an error, the errored state to return a value, and the excepted state to return a type erased smart pointer? Empty state is no different.
- exception() returns nullptr if holding value or error or empty
The current behaviour is to return null exception_ptr if valued (so if(eptr) would be false i.e. "no exception here"), std::make_exception_ptr(std::system_error(error())) if errored, throw on empty.
So an errored state is also an excepted state, but an excepted state is never an errored state. has_exception() returns true for either errored or excepted states.
std::make_exception_ptr(std::system_error(error())) is fairly cheap, a few thousand CPU cycles. std::exception_ptr's are heavy anyway.
I can understand that, but I'm not sure I can entirely agree with it. As previously mentioned an error_code return is supposed to indicate a non-exceptional error, while an exception is exceptional. So this feels like promoting a non-serious error to a serious error.
Sure. But this semantic also means that errors don't get accidentally lost if the programmer checks for an exception without checking for an error. I figured that to be a safer default.
Having said that, it's not a deal-breaker; both behaviours make sense in their own way, and that behaviour could be convenient in some cases.
Although... should it actually throw on empty or just return an exception_ptr containing an exception that indicates it was unexpectedly empty? The only place you should be using outcome<> rather than result<> is inside noexcept methods, so throwing is fairly serious.
In my own code to date my majority usage of outcome<> is in throwing code. I use it to "collect" try...catch islands, outside of the island writing exception safe code becomes considerably easier. I made empty the odd man out, so it always throws, consistently. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/