Niall Douglas wrote:
(and sorry Peter, your expected
design I am not persuaded by, but perhaps I am overestimating the brittle coupling generated by allowing every possible domain specific error type to bubble up to high level code)
This is not a design I personally find appealing - it's the equivalent of checked exceptions - but the fact remains that different libraries use different Es. Not a problem for result/outcome because the E is fixed.
If someone comes along with an obviously superior design to both Expected and Outcome, that would be an enormous win.
There's nothing much to improve upon in result/outcome as long as 4/5 of the stuff is thrown out. template<class T> class result { public: result(); // T() or error, legitimate fork result( T const& ); result( T&& ); result( std::error_code const& ) noexcept; result( result const& ); result( result&& ); result( outcome const& ); //? result( outcome && ); //? bool has_value() const noexcept; bool has_error() const noexcept; T value() const; T value() &&; std::error_code error() const; explicit operator bool() const noexcept; void swap( result& ) noexcept; }; That's literally it. As an extension, let's add the ring buffer: result( std::error_code& error, char const* message, uint32_t code1, uint32_t code2... ); result( std::error_code& error, extended_error_info const& info ); extended_error_info error_info() const; There we go.