Thank you, Jonathan, for your insights.

On 31/03/2025 09:42, Jonathan Wakely wrote:
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.


  1. 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.
Good point.
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