Le 24/05/2017 à 15:15, Andrzej Krzemienski via Boost a écrit :
Niall, What do you think about the following alternate interface of outcome types?
1. Remove option<T> altogether.
2. result<T> (and outcome<T>) does not have a separate empty state. Yes please.
3. A default-constructed result<T> is initialized as if `result<T>{error_code_extended{}}`. It is curious, the original expected
default initialized to E{} :) as I copied from optional. We moved to expected and a default construction as if T{} for two reason, to behave like T and to avoid this default construction of exception_ptr. 4. Function r.empty() is implemented as `r.has_error() && !error()`.
So you are requesting that error is explicitly convertible to bool. This
could work for outcome and result as the errors provide it but not for
expected
5. Framework requires that type E in `expected
` is default-constructible, and its default-constructed value represents no error condition (already the case for exception_ptr, error_code).
This is something that the library cannot check without adding more
constraints. The interpretation that the user does of each one of the
values of E is up to him.
If the Error parameter is not an error but a status, maybe the user
should consider the status_value proposal, which is isomorphic to
pair. In this proposal, some of the status values mean
succeed and others mean failure. The second is not empty if the status
mean success.
The default construction of exception_ptr is IMHO an accident.
If the user uses values of Error that doesn't mean an error, you have a
tri-state.
IMO, the use error_code{} or exception_ptr{} with outcome or expected is
an ERROR.
At the end I'm not sure result<T> or expected<T> should have a default
constructor. Note that we want variables initialized at the declaration
and the default construction of these types is always artificial.
The rationale behind this is my assumption that `option<T>` is not as useful as the other types. (Or can you give an example to the contrary?) That there was no initial business need for an empty state, and the examples that illustrate its usefulness are just exploring how we can make use of it now that it is there. (Or am I wrong here?)
I noticed a number of people report negative feedback about this empty state. Getting rid of it would take result<T> closer to "either T or reason for failure".
What do you think?
I agree with the non-empty, but disagree with the possibility of Error to mean a Status. This make the user code more complex. Concerning the default construction, I'm inclined to think that in this cases the best is to don't initialize as a T or as E. Note that this doesn't mean to add an additional state. The result of default construction is just a partial initialized state that needs either to be assigned or destructed, as if we had do a move. Trying to use has_value on this state will be UB. The advantage is that IMO, is that we don't spend more time than we need. Not all types should have a well formed object as default value (See e.g. chrono::duration, Date). Best, Vicente