Boost logo

Boost :

Subject: [boost] [outcome] High level summary of review feedback accepted so far
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-05-27 00:09:43

Some reviewers have asked what form Outcome will take in the near
future. The following is a high level summary of the changes already
made on develop branch or will be made according to logged from review
feedback. I have left out some minor issues, this lists just the major
changes. This should help reviewers to decide whether to recommend
acceptance or rejection. If there are any questions, please do ask.

Major design changes:
- option<T> to be removed

- outcome<T> and result<T> will have their empty state removed, and all
observers gain narrow contracts. Default construction is disabled. Example:

result<Foo> v(make_errored_result(std::errc::invalid_argument));
assert(v.has_error()); // true
assert(!v.has_value()); // true
// As if Foo(reinterpret_cast<Foo &&>
// (error_code_extended(std::errc::invalid_argument));
Foo f(std::move(v.value()));
assert(v.has_error()); // still true
assert(!v.has_value()); // still true

(NOTE: expected<T, E> will track whatever LEWG Expected does, but it
differs from what will become result<T> by having a wide contract on
.value() and narrow contracts on operator*(), .error(), operator->().
result<T> will have narrow contracts on everything, it is basically a
thin wrap of std::variant<T, error_code_extended> except with strong
never empty warranty)

- New typedefs outcome_e<T> and result_e<T> are identical to outcome<T>
and result<T> except for adding a formal empty state. Observer contract
slightly widens, an attempt to use an empty object throws a
bad_outcome_access exception. Implicit conversion from non-empty-capable
varieties is permitted to empty-capable varieties, but not the other way
round. Default construction is to **empty**.

- New typedefs checked_outcome<T>/checked_result<T>,
checked_outcome_e<T>/checked_result_e<T> are added. These mirror the
editions just described, but checks and default actions occur on all
observer usage so hidden reinterpret_cast<> never occurs. Implicit
conversion from non-checked varieties is permitted to checked varieties,
but not the other way round. Examples:

// Note result<T> implicitly converts to checked_result<T>, but not
// the other way round. So we can use same make_errored_result().
checked_result<Foo> v(make_errored_result(std::errc::invalid_argument));
assert(v.has_error()); // true
assert(!v.has_value()); // true
// .value() throws std::system_error(
// std::make_error_code(std::errc::invalid_argument));
Foo f(std::move(v.value()));

checked_result<Foo> v(make_valued_result(Foo()));
assert(!v.has_error()); // true
assert(v.has_value()); // true
// .error() returns a default constructed (null) error_code_extended
// when result is valued to indicate "no error here"
error_code_extended ec(std::move(v.error()));
assert(!ec); // true

- The presented library self generates using lots of preprocessor based
multiple #include's to stamp out finished editions of implementation.
The git repo partially preprocesses this into a nearly finished edition
for minimum compile time load for end users.

Due to the many more varieties of outcome<T> and result<T> provided, the
preprocessor machinery would be replaced with a template based machinery
instead. I will look into making optional use of extern template and a
static library to retain minimum compile time load, but header only
usage will remain possible.

Smaller design changes:
- tribool stuff to go away in default configured build.

- .get*() functions will be removed.

- Don't include <windows.h> on winclang.

Documentation changes:
- Licence boilerplate missing on some files.

- Reference API docs need to spell out exact preconditions,
postconditions and semantics per API.

- Reference API docs need to describe types void_rebound, *_type and
raw_*_type in detail.

- User overridable macros which throw exceptions and provide
customisation points have vanished from the docs somehow.

- Landing page and introduction to be broken up into bitesize single
page chunks.

Still to be decided:
- Should *_e() varieties provide convenience .get(), .get_error(),
.get_exception() which returns T, error_code_extended and
std::exception_ptr by value moved from internal state, resetting state
afterwards to empty? These would mirror future.get()'s single shot


ned Productions Limited Consulting

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