2017-05-30 9:27 GMT+02:00 Gavin Lambert via Boost
On 30/05/2017 18:45, Vicente J. Botet Escriba wrote:
Le 30/05/2017 à 01:41, Gavin Lambert a écrit :
FWIW, my preferred options would be (which I think were the originals):
Thanks, you are the first (I believe) that supported the proposed interface, but maybe I'm wrong.
I think my suggestions aren't quite identical (in particular I think empty is handled differently in some cases). But they're close.
- value() throws if holding error or exception (or empty)
- error() returns E{} if holding value or E{errc::has_exception} if holding exception, or E{errc::no_value} if empty (names made up on the spot, doesn't matter)
Would you like to extract the error code from the stored exception If the exception had an error_code() function?
If that's fast and noexcept, maybe. Otherwise it's probably not worthwhile. It's probably a coding error for a method that wants error_codes to call something that throws system_errors.
So the error codes must contain also the success codes. And now we don't
know if errc::no_value means success or failure.
Niall's stated in other threads that in actual usage, sometimes empty is a success and sometimes it's a failure. So the decision of which it is has to be left to the caller, who presumably knows what it actually means.
I expect that in a handling-empty code path, error() would never be called, or if called, would be stored in a variable that is later discarded. But the suggested behaviour makes it safe to use even if the code doesn't check for empty and does make use of the error code.
Wondering id make_error_code isn't more appropriated. I know you don't
like long names, but this is what the function is doing.
In this context I'm describing behaviour absent of any judgement on what the things are actually called. Though FWIW both names are a little suspect since you'd expect make_error_code to actually return a std::error_code. make_unexpected from your proposal is more sensible in that regard; I suppose make_error_result or something like that would be more correct in this case.
Doesn't really matter too much as people can "using" bikeshed their own names in fairly easily.
- exception() returns nullptr if holding value or error or empty
Why not create an exception when there is not, for the other cases?
I can see an argument for returning a std::exception_ptr containing a std::system_error in the case where there is an error code.
However I'm not convinced that this is the correct choice. The purpose of having an error code is to indicate non-exceptional failure, so synthesizing an exception from one in this case seems dubious.
That is an important observation. Would everyone in this discussion agree that whenever there is an incorrect usage of `outcome` detected (like extacting vaue when we are storing an error code, or extracting error code when we are storing an exception_ptr) it is uniformly signaled by BOOST_THROW_EXCEPTION() (or some such)? No E{}, no translations: just BOOST_THROW_EXCEPTION()?
Without this interface we can say the it is UB to have an exception_ptr
with a nullptr stored in an outcome. Now that we can get one of those, it is much difficult to reason about.
Reasoning about defined behaviour is surely easier than reasoning about undefined behaviour?
No. When you know some states of the object are illegal, you can easily tell when someone is using the library incorrectly. And you can fis the pfoblem more quiclkly.
But I would like a single semantic for functions with the same name.
What does this mean? I'm not sure how it applies here as we're talking about methods with different names.
So you are not one of those that needs the more efficient interface. When
you know the precondition is satisfied, why do you want to pay for additional checks on the library and on the user code? If you provide the minimal interface the user can built on top of it whatever he needs. Not providing it will imply that all will pay for.
Perhaps I am mistaken, but I generally prefer an overly-defensive coding style with explicit precondition checks on public interfaces. I don't trust developers (including myself) to write correct code and I don't trust them to run static analysers on their incorrect code.
Regards, &rzej;