Something not really mentioned until now is how Outcome interoperates with the proposed
, whose design lands in between
unchecked<T, E = varies>
checked<T, E = varies>
(both of which are type aliases hard coding no-value
policies as previously covered in this tutorial).
Expected and Outcome are isomorphic to one another in design intent, but interoperation
for code using Expected and Outcome ought to be seamless thanks to the proposed
concept framework, a subset of which Outcome implements.
explicit basic_result(concepts::value_or_error<T, E> &&)
explicit basic_outcome(concepts::value_or_error<T, E> &&)
constructors will explicitly construct from any type matching the
concept, which includes
std::expected<A, B>, if
A is constructible to
value_or_error concept in turn is true if and only if the input type has:
.has_value()observer returning a
Outcome’s machinery for implementing
concepts::value_or_error conversion is user extensible by injection
of specialisations of the
type into the
convert::value_or_error<T, U> implementation explicitly
outcome types from the default mechanism as
there is a major gotcha: the
value_or_error matched type’s
.value() is often
not callable in constexpr as it can throw, which makes this conversion mechanism
pretty much useless for constexpr code. Besides,
outcome has a converting
constructor overload for
result inputs which is constexpr capable.
Note that if you do enable
outcome inputs, a
result will match an input
outcome, but silently dropping any exception state. This is probably undesirable.
Examples of how to implement your own
convert::value_or_error<T, U> converter
is demonstrated in the worked example, next.