Boost logo

Boost :

Subject: Re: [boost] Boost.Outcome review - First questions
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-05-24 15:20:54

>>> IIUC, what you want is to have outcomes that copy/move well each one on
>>> each other.
>> That was exactly a motivating reason for choosing this design
>> originally. Having the same base storage implementation should allow the
>> compiler to completely eliminate memory copying to implement layout
>> changes when a personality is changed.
> How outcome ovoids this copying?

Compilers spotted the common outcome::value_storage during moves when it
was identical, and totally eliminated any memory copies.

>>> Is this the major drawback you find to the use of
>>> std::expected and std::optional?
>> No, not at all. Very recent optimisers e.g. in better than clang 4.0 and
>> in GCC 6.0 with -O3 optimisation turn out to have rendered the common
>> storage design choice no longer appropriate. But that wasn't the case
>> when I began Outcome two years ago.
> And then?

clang 4.0+ and GCC 6.0+ with -O3 optimisation appear to now be clever
enough to spot trivial move constructors and trivial types, and not copy
memory when the bits in memory would not change.

I would therefore expect that your reference Expected implementation
would now be identical or very similar in runtime performance to Outcome
on clang 4.0+ and GCC 6.0+. MSVC does, of course, still have some way to
go yet, but VS2017 is a world of improvement over VS2015.

>> You would thus exchange (slightly) worse performance of successful code
>> in exchange for vastly better and predictable performance of
>> unsuccessful code.
>> Note that the cost of throwing and catching a C++ exception with a table
>> based EH C++ compiler is highly unpredictable, and costs between
>> 1500-3000 CPU cycles per stack frame unwound between the try and catch
>> site. You can find the benchmark in the benchmark directory in Outcome's
>> git repo.
> So you are comparing to the use of exceptions here and not to the use of
> output error codes?

I am comparing the cost of throwing and catching exceptions to returning
an expected with unexpected state.

>>> What is the behavior on the absence of exception on the functions that
>>> throw exceptions? Are these functions disabled? Does the fucntion
>>> terminate? Calls a handler?
>> All exceptions Outcome ever throws are done via a user redefinable
>> macro. Those macros are listed at
>> If C++ exceptions are enabled, the default macro definition throws the
>> exception.
>> If C++ exceptions are disabled, the default macro definition prints a
>> descriptive message and a stacktrace to stderr and calls
>> std::terminate().
> This is similar to what BOOST_THROW_EXCEPTION does, isn't it?
> Why re-invent the wheel?

End users can define the Outcome exception throwing macros to call
BOOST_THROW_EXCEPTION if they wish. For standalone Outcome users, the
default behaviour is minimal, but sufficient.

>>>> is an
>>>> excellent neighbour to all other C++ libraries
>>> as for example?
>> It pollutes no namespaces, interferes in no way with other C++ including
>> other versions of itself. You can mix multiple versions of Outcome in
>> the same binary safely.
> There are several version of Outcome?

Currently every time I commit to the git repo there is a new version of
Outcome. The ABI is permuted with the SHA of the git. This prevents
unstable versions of Outcome conflicting with different unstable
versions of Outcome in the same process.

I will, at some future point, declare a stable ABI and pin it forever to
v1 of the ABI and have that checked per commit by Travis.

>>>> AND build systems,
>>> I'm less concerned by the build systems, but could you elaborate?
>> Outcome doesn't require any magic macros predefined and can be used by
>> end users simply by dropping a tarball of the library into their source
>> code and getting to work.
> While this could be a quality for a standalone library, this is not a
> quality for a Boost library.

The other C++ 14 library in Boost does not require any of Boost either.

>>>> (And my thanks to Andrzej for the motivating example on the landing
>>>> page
>>>> of the docs, he did a great job capturing the universal error handling
>>>> framework aspect of Outcome. I would love to know if reviewers can make
>>>> sense of it, or did it just confuse the hell out of everybody)
>>> Could you tell us which example?
>> It's the landing page motivating code example. Bottom of
> No this example doesn't show any advantage of Boost.Outcome, quite the
> opposite. However the other example that Andrzej has posted recently is
> a better example as I have already said as a response.

The only difference was returning result instead of outcome, and
removing the exception throwing function call. Otherwise the examples
are identical.


ned Productions Limited Consulting

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