Boost logo

Boost :

Subject: Re: [boost] Outcome v2
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2017-07-17 20:46:52

On Sun, Jul 16, 2017 at 7:00 PM, Gavin Lambert via Boost <
boost_at_[hidden]> wrote:

> On 14/07/2017 06:09, Emil Dotchevski wrote:
>> If std::error_code is sufficient, put your money where your mouth is and
>> go
>> back to outcome v1 where the only choices were std::error_code and
>> std::exception_ptr. But the reality is that std::error_code is not
>> sufficient (perhaps not due to its own deficiencies); in practice you do
>> need to be able to transport more or less arbitrary error types.
> I think the issue is that while std::error_code is sufficient to convey an
> error *code*, it is not sufficient to convey an error *context*.

You're saying that std::error_code is fully capable of conveying _what_
went wrong. This is true, but is it sufficient for an error handling
library to only support std::error_code for this purpose? The answer in v1
was "almost", as it also supported std::exception_ptr. The answer in v2
seems to be "not at all", since it turned both into template parameters.

The context part is a separate issue and you're right that it can be
provided independently of the error type.

> Outcome v1 solved this by standardising on a slightly-larger type that
> conveyed a specific small set of additional data, which was deemed good
> enough for most uses -- but there's still a bit of sacrifice involved there
> since it would be too much for some cases and too little for others,
> combined with the separated storage causing it to sometimes go away
> unexpectedly.

Yes, it was a compromise, which is the result of the decision to transport
error objects into the return value of functions. This design -- and the
compromises that follow from it -- would be more reasonable elsewhere, but
in error handling very few functions need to interact with the error
object. That is why it makes more sense to push it out of the critical path.

I mentioned in a discussion thread at the time that it might be useful to
> consider having multiple user-defined derived subtypes of std::error_code
> (or one standard templated one) to add additional context state, similar to
> how std::exception is subclassed to add additional state to that. Though
> this has some downsides as well, mainly requirement to not pass by value
> (unless you want to slice off the extra data) and possible introduction of
> memory allocations (eg. if std::string were in the payload), which also
> discourages pass-by-value.

If you enable subclassing, you're enabling more or less arbitrary types. At
that point there is little value in mandating std::error_code as the only
acceptable base type, in fact it makes more sense to use std::exception.
You're right about memory allocations, but while they are not permissible
in some cases in others they can be used, and should be supported.

> Outcome v2 appears to have chosen a different path, where you mostly still
> use unadorned std::error_code (although since it's templated it's possible
> you could still do the above) but you also get an extra arbitrary payload
> pointer *or* an exception_ptr (where then presumably your extra payload is
> carried in a particular exception subclass). I'm still a bit on the fence
> about that latter option; exception_ptrs are a bit of a pain to extract
> useful information from.

It is true that std::exception_ptr probably needs facilities to inspect the
object it contains.

Boost list run by bdawes at, gregod at, cpdaniel at, john at