Boost logo

Boost :

Subject: Re: [boost] [outcome] Possible extensions/changes to std::experimental::expected
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2017-05-26 05:16:04


Le 26/05/2017 à 03:00, Gavin Lambert via Boost a écrit :
> On 25/05/2017 19:44, Vicente J. Botet Escriba wrote:
>> 3. uninitialized default constructed expected<T,E>
>
> I've already stated my opinion on this elsewhere.
Point taken.
I'll ask the committee to consider removing the default constructor.
>
>> Outcome doesn't implement comparisons between Outcomes. He pretend
>> that we don't need them. In addition the mix of comparisons and
>> implicit conversion give us some surprising cases as described in
>> Andrzej blog.
>
> I agree with Niall -- putting one directly in an ordered collection is
> bizarre and if someone really wants to do that then it should be left
> up to them to define what ordering makes sense to them. operator<
> should absolutely not be implemented and I would hesitate before
> providing any free standard ordering methods.
As I said elsewhere, you (all) have convinced me. I'll suggest to remove
them on the next revision.
>
>> The implicit conversion from T to expected<T,E> is a consequence of
>> wanting that expected<T,E> should behave like a T. But this is not
>> right. A expected<T,E> is not a T.
>
> Implicit construction does not imply is-a, it implies is-superset-of.
> Which is true, expected<T,E> is a superset of T. As the intent is to
> naturally convey T as a wrapped return value of a method, the implicit
> construction allows "return some_t_value;" as a simplified syntax and
> the most natural one. Forcing users to use "return
> make_expected(some_t_value);" instead would be a disservice and
> discouragement, I think.
I like the explicitness of make_expected. I'll ask the committee to
consider explicit construction as a safer design.
I understand people like implicit constructors until they find that they
don't want them here or there.

void f(optional<T>);
T x;
f(x);

Later on add
void f(expected<T>);
T x;
f(x); // ambiguous :(

So T is a subset of two sets and then we need to be explicit. Been
explicit from the beginning avoids surprises.

>
> (In order to imply is-a then there must be a reverse conversion
> operator from expected<T,E> to T, and that definitely should not
> exist, not even as explicit.)
>
> The caveat (and the reason make_unexpected is required) is where T and
> E are compatible, eg. expected<int, int> or expected<double, int>
> etc. In this case there is a possibility that someone intending to
> return an error value might forget to use make_unexpected and end up
> with code that compiles but is not correct. Requiring explicit
> make_expected does mitigate this case but I'm not sure it's worth the
> hassle.
>
No, I wanted to have make_expected/make_unexpected from the beginning as
we are explicit in Haskell

Either T U = Left T | Right U

but people wanted that expected<T> should behave as much as possible as
a T. I don't think this is a good thing. I don't mind to be explicit in
this case as it is clearer and more robust.

> Outcome uses a different mitigation by restricting the possible types
> of E, rendering the above case very unlikely (although not impossible,
> since outcome<error_code> is legal).
Outcome T U = T | U

and that implies that both are different.

Even if we wanted that expected<T,E> is valid only if T is different
from E, I believe the explicitness has added value.

>
>> My question is why don't throw directly E?
>>
>> Some are requesting a way to get a specific exception from E, but
>> either there is one exception that works for all and we can set it
>> using some kind of trait or we need to add a trait parameter to
>> expected to the the mapping :(
>>
>> Do we really want this to be configurable?
>
> At least where E happens to be std::error_code it would be nice if it
> threw std::system_error, since that is the exception designed for such
> things. Otherwise I have no opinion.
Are you saying that you are for hard coding this mapping?
What other hard coded mappings do we neeed?
     exception_ptr -> the contained exception

Others?

Thanks for the feedback,
Vicente


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