Boost logo

Boost :

Subject: Re: [boost] [outcome] Change semantics on UB from peer review agreed semantics?
From: Peter Dimov (lists_at_[hidden])
Date: 2018-09-13 00:54:23


Gavin Lambert wrote:

> To clarify, I was wondering if we should:
>
> 1. Implement an error-to-exception conversion trait as a generic
> template which does not compile by default.
> 2. Provide a specialisation for boost::system::error_code which returns
> boost::system::system_error.
> 3. (Where supported by the STL) Provide a specialisation for
> std::error_code which returns std::system_error.
> 4. Allow users to provide additional specialisations for other error
> types.
> 5. Provide generic boost::throw_error which calls boost::throw_exception
> on the result of the conversion trait.
> 6. Make Outcome's default policy call boost::throw_error instead of hard
> UB.

Looking at my various expected/result experiments, what I've done there is:

- in expected<>, I call `throw_on_unexpected(e)` unqualified, and if that
returns, I throw bad_expected_access<E>(e):

https://github.com/pdimov/variant2/blob/81023c3569b3edcd9c5d631862905744e20cd9c5/include/boost/variant2/expected.hpp#L141
https://github.com/pdimov/variant2/blob/81023c3569b3edcd9c5d631862905744e20cd9c5/include/boost/variant2/expected.hpp#L93

- in (one) result<>, I call error_code_to_exception(e) unqualified, then
throw the result:

https://github.com/pdimov/result/blob/e7f0b076e267111098e49d8e7f7c15b5dbb7cad8/include/boost/result/result.hpp#L521
https://github.com/pdimov/result/blob/e7f0b076e267111098e49d8e7f7c15b5dbb7cad8/include/boost/result/result.hpp#L90

However, I vaguely remember that I convinced myself at one point that the
latter (calling a function to convert) is inferior to calling a function
that throws. For one thing, you can't convert an exception_ptr to an
exception (*); for another, sometimes you want to throw different exceptions
based on the runtime value of the error code (bad_alloc on ENOMEM for
instance.)

So I would probably go with calling `throw_exception_from_error_code(e)`
unqualified nowadays. (And follow that call with __builtin_unreachable(),
allowing diehard fans of undefined behavior to obtain it by returning.)

(*) This is needed, for instance, when you build an outcome<> on top of a
result<> by

struct my_error_code
{
    std::error_code code_;
    std::exception_ptr exc_;
};

template<class T> using outcome = result<T, my_error_code>;

Now you want something like this:

void throw_exception_on_error_code( my_error_code const & e )
{
    if( e.exc_ )
        std::rethrow_exception( e.exc_ );
    else
        throw std::system_error( e.code_ );
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk