Boost logo

Boost :

Subject: Re: [boost] expected<T, E...> (Was: [outcome] High level summary of review feedback accepted so far)
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2017-06-04 21:48:46


Le 04/06/2017 à 22:40, Peter Dimov via Boost a écrit :
> Gottlob Frege wrote:
>> On Sun, Jun 4, 2017 at 12:35 PM, Peter Dimov via Boost
>> > Perhaps the heuristic could be, if the argument can be interpreted
>> as > both a value and an error, the conversion is ambiguous,
>> regardless of > which of the two is a better match. This will make
>> the above return > ambiguous, which is probably as it should be.
>>
>>
>> I think I might agree with that.
>> There will definitely be cases where expected<T,E> has T == int and E
>> == int, and worse, sometimes those cases will be:
>> - T is a template param, so you don't "see" that it is sometimes an int
>> - E is a #define or platform-defined, etc, so it is only _sometimes_
>> an int
>
> T == int, E == int is not a problem, because it will always be
> ambiguous. The thorny case is E == int, T == something convertible
> from int, such as double, long, unsigned.
>
>
Lets imagine ofr a moment that we allowed implicit conversion from
convertible to T and convertible to E as far as both constructions are
not possible.

     expected<double, unscoped_error> test()
     {
         return unscoped_other_error; // Compile Error as ambiguous
     }

     expected<double, unscoped_error> test()
     {
         return make_unexpected(unscoped_other_error);
     }

Then if we want to be more explicit, then we can use wrappers that force
us to be explicit: expected_ and unexpected_ are wrappers that are
explicitly constructible from the wrapped type and provide explicit
access to the value.

     expected<double, unexpected_<unscoped_error>> test()
     {
         return unexpected_{unscoped_other_error};
     }

  Note that unexpect_<E> can not be implicltly convertible to E as
otherwise we will have again an ambiguity.

If we want also to be explicit on T

     expected<expected_<double>, unexpected_<unscoped_error>> test()
     {
         return expected_{3.0};
     }

The problem now is that we need to unwrap the wrapped types as the
conversion is not implicit.

My original design with an implicit unexpected_type was to avoid this
unwrap operation, and define getter for unexpected_type<E> and also for
the wrapped E.

Given an expected that has the implicit constructors, we can build
another expected_expl that has his constructors explicit and provide
unwrapping operation.

The same can be achieve from a expected that has explicit constructors,
we can define a expected_impl that has his constructors implicit.

Do we need both approaches? I don't know..

Vicente


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