Boost logo

Boost :

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


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.

Boost list run by bdawes at, gregod at, cpdaniel at, john at