optional<T> is an asymmetric type safe union of
T and nothingness (
nullopt_t). You can query if it has a
explicit operator bool, and get the
T out with unary
*. The asymmetry means that optional “prefers” to be a
T, which is why unqualified operations (like
* or operator bool) refer to its
variant<A,B,C> from paper n4218 is a symmetric type safe union of
boost::variant is always engaged, and
std::variant is almost always engaged (in order to preserve some exception guarantees, it can become valueless by exception if the types it store don’t have the right exception semantics).
As it is symmetric, there is no unique type for unary
* to return, and
explicit operator bool cannot say much of interest, so neither are supported.
Instead, you have to visit it, or query it for particular types.
std::expected<T, E> from paper n4015 is an asymmetric type-safe union. It is either a
T, or an
E. But like
optional, it “prefers” to be a
T; it has an
explicit operator bool that tells you if it is a
T, and unary
* gets the
In a sense,
expected<T,E> is an
optional<T>, but when empty instead of wasting the space it stores an
E, which you can query.
Result<T,E> seems close to
expected<T,E> (note that as of n4015, the order of parameters are swapped compared to
Result, but the published version did not).