Thank you, Jonathan, for your insights.
std::optional<T&> is explicitly not allowing rvalue references, I don't see the committee going the other way for std::expected.
Maybe I missed something, but P2988 doesn't seem to mention
rvalue references, neither proposing nor actively disallowing
them. Has there been any discussion on
std::optional<T&&> at all, or it simply not (yet)
proposed? P2988's given rationale for optional<T&> is
that any type that std::tuple accepts should work with
std::variant (and by extension, work with std::optional and
std::expected). As std::tuple supports both lvalue and rvalue
references, perhaps allowing rvalue references for both
std::optional and std::expected (and std::variant?) is a potential
next step.
Good point.
- std::exception_ptr::value() called std::rethrow_exception(error()) rather than throwing a std::bad_expected_access on error, and
What if the error() is a null std::exception_ptr? The rethrow would have undefined behaviour in that case.
As nice as some of these changes might be, they would mean ABI breaks if we did it now. For std::expected<T&, exception_ptr> we could do anything, because that doesn't exist now so there's no compatibility with existing code to worry about. But it would be strange if it had a completely different API from the non-reference std::expected<T, exception_ptr> form.
One solution would be to introduce a tag type that can be used as the second template argument to request the behaviour you want, e.g. std::expected<T, std::handle_exceptions_cleverly>, but with a better name :-)That tag type doesn't exist today, so there would be no compatibility concerns here either. Anybody using the tag type is explicitly opting in to the alternative API. The error_type could still be defined as exception_ptr, rather than the tag type, and the monadic operations could be modified to catch exceptions from the callable. Something like a tag type was the (weakly) preferred direction for P3014
If I understand you correctly, specialising std::expected<T, new_tag_type> would be acceptable on the basis that new_tag_type is new, rather than because it is a tag type per se. The downside of a tag type is that it breaks the pattern of the type parameters <T, E> denoting the types <value_type, error type>. But what if we specialise std::expected on a new error type std::non_null_exception_ptr? I think this resolves the issue of ABI compatibility and avoids the problem of a null error_type. There's even a reasonably good name for it :-)
--
Stewart