Subject: Re: [boost] [gsoc-2013] Boost.Expected
From: Pierre T. (ptalbot_at_[hidden])
Date: 2013-04-23 02:59:24


Hello,

On 04/22/2013 06:45 PM, Gottlob Frege wrote:
> A few thoughts about expected<> :
>
>
> I think comparison with optional<> is worthwhile. In fact, I think we
> should consider small changes to optional, if necessary, if it helps them
> align. Specifically I'm thinking of the cast to bool. Does the below
> conversions to bool bother anyone?
>
>
> std::expected<int, Err> exp = ...;
> std::optional<int> opt = ...;
>
> if (opt) {
> ...
> }
>
> if (exp) {
> ...
> }
>
> And if that doesn't bother you, change the 'int' to 'bool' above.
>
> I don't care which way it goes (the alternative being a explicit function
> call, like exp.valid() or is_valid() or...), but I think it makes sense for
> expected and optional to work the same way, and currently, optional<> is
> set to work in the above. So if you really dislike if (exp), then you have
> an uphill battle to change optional, which was just accepted.
>
>
> As for comparing "exceptions", I'm not sure the exception part of expected
> should be always considered an exception. Maybe it is just the "false
> case" type. ie
>
> expected<true_case, false_case>
> or
> expected<expect_type, else_type>
>
> or however you want to think of it.
>
> I would only call it an *exception* type if it gets thrown when trying to
> access the value of a false expected:
>
You right, we should align on std::optional, at least for the bool cast.
>
> std::expected<int, Exception> exp;
>
> int x = exp.value(); // has no value - does this throw bad_expected_access,
> or does it throw Exception()?
>
Actually, expected contains an error and we don't know anything about
the type of the error so we cannot throw it. It's what I called
expected_base<T, Error> in my previous mails, the get() on expected_base
doesn't throw and if expected_base doesn't contain a value, then
undefined behavior occurs.

Currently, we thought about two refinements of expected_base, the first
is expected<T> as described by Alexandrescu in his talk. It contains
some nice features related to exception, so in this case, the get()
throw the contained exception if it doesn't contain a value.

The second is expected_or_error<T> in which the error is a
std::error_condition. The behavior of the get() method is not yet
well-defined and could eventually throw a bad_expected_access.

One of my concerns about it, is the double check:

if(e.valid()) // test if e is valid
   f(e.get()); // re-test

And this is why the get() method in expected_base doesn't contain any check.

Another concern is about the class name, in my proposal, expected and
expected_or_error privately inherits from expected_base. expected should
be named "expected_or_exception" to be logic. This is relevant because
it means that the design is unclear and we "favor" the Alexandrescu
expected instead of having an expected<T, Error>.
>
> I think answering these questions might help answering the comparison
> questions. ie first know what expected<> really is.
>
> Tony
>
Should expected be a generic component on the error type such as
Expected<T, Error> (and with refinements for exceptions and
error_condition), or should it be the Alexandrescu Expected<T> with
another class specialized for error code that aren't exception ?

I quite digress from your initial questions, but you made realized some
important points.

Thanks for the comments,
Pierre T.