Boost logo

Boost :

Subject: Re: [boost] [outcome] outcome without empty state?
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-05-24 20:33:10


>> 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).

std::error_code does not have a constexpr constructor, and does not have
a constexpr .value() nor explicit operator bool(). Very unfortunate. It
also precludes doing a generic check that a default constructed E tests
to boolean false, so you will need that generic check plus a special
override for std::error_code and subclasses of std::error_code.

>> 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.

I would agree.

A null error_code has the convention of "no error here", but as I've
explained in previous discussion, because of the C++ standard requiring
system_category with a code of 0 for default construction, it rules out
anyone *portably* treating a null error_code as "no error here".

Until the C++ standard gets fixed, we cannot assume this of the null
error code any more than the Filesystem TS does (which it does,
incidentally, and it should not).

> 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.

I disagree. That is on the end user to decide, not us.

> 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.

I too felt this, which was one of my rationales for the formal empty
state. Completely eliminating the default constructor altogether does
seem attractive ... but it would be a usability pain for end users.

> 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.

Ah, more UB. Yay.

> 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).

If the formal empty state is to be removed, then either you default
construct T, or E, or you go the UB route. I still find the formal empty
state the most attractive, but I recognise no one agrees with me.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/

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