ValueOrError Concept
Something not really mentioned until now is how Outcome interoperates with the proposed
std::expected<T, E>
, whose design lands in between outcome::unchecked<T, E>
and outcome::checked<T, E>
, both of which are simplified aliases for outcome::result<T, E>
hard
coding the NoValuePolicy
to a fixed policy.
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 ValueOrError
concept framework, a subset of which Outcome implements.
Outcome’s result<X, Y>
will explicitly construct from any type matching the ValueOrError
concept, which includes std::expected<A, B>
, if A
is constructible to X
and B
is
constructible to Y
. The ValueOrError
concept in turn is true if and only if the input type has:
- A
value_type
anderror_type
member typedefs. - A
.has_value()
observer returning abool
. .value()
and.error()
observers.
Implementation
Outcome’s machinery for implementing ValueOrError
conversion is user extensible by injection
of specialisations of the value_or_error<DEST, SRC>
type into the BOOST_OUTCOME_V2_NAMESPACE::convert
namespace.
Outcome’s default convert::value_or_error<DEST, SRC>
implementation explicitly excludes Outcome result
and outcome
types from the default mechanism as there is a major gotcha:
Outcome’s .value()
is often not callable in constexpr as it can throw, which makes this mechanism pretty much
useless for constexpr code. Thus separate explicit converting constructors exist which constexpr convert
from any Outcome type (though note that result
construction from outcome
does use the
ValueOrError
mechanism).
Examples of how to implement your own convert::value_or_error<DEST, SRC>
converter
is demonstrated in the worked example, next.