Boost logo

Boost :

Subject: Re: [boost] [review] Review of Outcome v2 (Fri-19-Jan to Sun-28-Jan, 2018)
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2018-02-02 22:26:01


On Fri, Feb 2, 2018 at 1:19 AM, Niall Douglas via Boost <
boost_at_[hidden]> wrote:

> > In contrast, Boost.Outcome is intended for usage in these rare cases were
> > "forward up and abort" is not the thing you would like to do most of the
> > time. Its goal is not to handle failures anywhere, but to solve a
> specific
> > problem in specific places. I believe that the criticism of Boost.Outcome
> > should be in this context of places where "forward up and abort" is not
> > what you typically need to do.
>
> And this really drives to heart of what I don't get about your arguments
> Emil. Outcome is really an abstraction layer for setting per-namespace
> rules for when to throw exceptions. Exception throwing is absolutely at
> the heart of Outcome. That's why Outcome != Expected, and why it ICEs
> older compilers, and why C++ 14 is needed.
>

Consider the following library:

template <class T,class E> class result; //contains variant<T,E>

conversion to bool returns true if result was initialized with T, false
otherwise;

.value() returns T& or calls boost::throw_exception(error());

.error() returns E& or undefined behavor.

You could use this library together with exception handling: it helps with
annoying exceptions when you can handle the error locally, otherwise you
just call .value() and let exceptions do their thing.

The question is what to do under BOOST_NO_EXCEPTIONS. Presumably you could
go with E=error_code, but that is inadequate for forwarding arbitrary
errors, making the library impractical to use without exceptions -- and we
want a library that is practical to use without exceptions. Correct me if
I'm wrong, but I think that you and I agree on this.

So, my vote is based on (in no particular order):

1) In these discussions, I can clearly recognize the dislike for exception
handling and even C++ (I don't mean by you personally) that I have been
exposed to in the past, since for years I've been surrounded by people who
falsely believed that they can't afford exceptions or smart pointers or
proper serialization, and they have strong, if incorrect, opinions on
what's wrong with C++. I believe that this attitude does not belong to
Boost. It's possible that I got this wrong. It may be interesting to know
how many of the current users of "standalone" Outcome use Boost in "low
latency" environments or at all. Do you have an idea?

2) Clearly, Outcome _does_ want to help pass errors across API boundaries,
including in generic contexts. The problem is that

result<T,E> compute() noexcept;

is very similar to

T compute() throw(E);

(yes, I know exception specifications are enforced dynamically, but that's
not what's wrong with them, see the second question here:
https://herbsutter.com/2007/01/24/questions-about-exception-specifications/
.)

My reasoning is that if with Outcome you can always return the exact error
type you've specified in your static interface, the same approach would
work for (perhaps statically-enforced) exception specifications.

Logically, to address this concern you could:

- Demonstrate that there is a major flaw in my analogy, or

- demonstrate that exception specifications could be made practical,
including in generic contexts, possibly by using some clever policy-based
design, or

- provide an interface that can forward arbitrary errors ot the caller.

(I see these as mutually-exclusive).


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