Boost logo

Boost :

Subject: Re: [boost] [outcome] outcome without empty state?
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2017-05-24 15:33:40


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<E,T> default initialized to E{} :)
as I copied from optional.
We moved to expected<T,E> 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<T,E>.
I don't believe the library should make use of this bool conversion.
Even the opposite. I will add a pre-condition that the Error value if
convertible to bool is equal to false (this can be also cheched at
run-time).
>
> 5. Framework requires that type E in `expected<T, E>` 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<S, T> proposal, which is isomorphic to
pair<S, optional <T>>. 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk