Boost logo

Boost :

Subject: Re: [boost] [outcome] On the design and documentation
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2017-05-26 05:38:44


On 05/25/2017 01:01 AM, Niall Douglas via Boost wrote:
>> First of all, I don't agree with the strong (conceptual) relationship between
>> optional (be it boost:: or std::experimental) in such a way that expected is a
>> generalization of it. From what I understand, the purpose of expected/outcome/
>> result is to be used as a mechanism to return the result of a function. As
>> such it should also expose the semantics of it. Fortunately, we already have a
>> (asynchronous) return object standardized (std::future). And this is my basic
>> disagreement here: Why not model expected in the lines of future? With the
>> main points being:
>
> An earlier edition of Outcome did implement future-promise. I think you
> yourself reviewed it then.

We reviewed AFIO, which included outcome. Back then Outcome did indeed
try to implement future-like semantics with semantic/interface changes
which were discussed and found to be inappropriate. This is a different
topic since you decided to define different semantics, again with lots
of food for discussion.

>
>> - expected being movable only
>> - expected<T,E>::value() should always return by value and invalidate this.
>
> As I mentioned in a reply to Peter yesterday, I am attracted to these
> semantics.

There are a lot of unanswered questions coming along with that design
decision...

>
>> Second, I think Niall raised a valid about outcome being a framework for
>> interoperability (completely orthogonal to the first point). However, I totally
>> miss this from the proposed library, most pressing are non intrusive
>> mechanisms. For that purpose I postulate, that a mechanism to transform
>> between different unexpected results, that is: various error codes etc.
>> However, for that to work, one would of course need a properly defined concept,
>> for example, as Vicente suggested "EitherValue", and a mechanism to coerce one
>> error type into another, maybe through ADL, or traits specialization or
>> whatever.
>
> <system_error> already provides equivalence testing between
> std::error_code's.

I am not talking about equivalence testing or the ability for ones own
categories. I am talking about conversions between two different error
types.

>
>> Furthermore, I believe that .value/.error should really have a narrow
>> contract, that is that it is UB to call those functions if the respective
>> types are not held (easy to catch this in a debug build...). Why? Probably
>> just a micro optimization, but consider the canonical usage:
>> auto r = some_function_returning_expected(...);
>> if (r.has_value())
>> // Do something with the value
>> else
>> // An error occurred, PANIC
>> In both branches, we know exactly what's in there ... so why check again when
>> getting the state out?
>
> If you've already checked by hand, the compiler will elide the internal
> check entirely.

That's quite a claim to make here. When looking at vector<T>::at, this
is certainly not the case, unless compilers made significant
improvements over the last few years.

>
>> When I open its "landing page", I get no idea about the following:
>> - What is the purpose of the library?
>> - Why/when should I use it?
>
> It quite literally tells you both on the landing page.
> https://ned14.github.io/boost.outcome/index.html.

 From an empirical study of a non representative group, it seems it is
not as literal as you would like it to be.
One thing is that the points I mentioned are not visually
distinguishable at first sight, there are three paragraphs with lots of
prose.

The first paragraph reads:
"This is the Outcome library. It is a C++ 14 library intended to aid
ultra-lightweight error handling in large C++ codebases, providing a
more expressive and type safe alternative to integer error codes or enums."

Apart from the trigger word "ultra-lightweight", what the library
actually does is at the very end in a long sentence.

The second:
"Unlike alternative implementations, it works perfectly with exceptions
and RTTI disabled and is thus suitable for
low-latency/games/finance/SG14 users. One could view Outcome as a
minimum overhead universal outcome transport mechanism for C++, hence
being named "Outcome"."

This sentence starts with "Unlike alternative implementations", I don't
even know what to expect from this library, at this point, I really
don't care about the alternatives yet, speaking of which, which
alternatives? The key feature you wanted to highlight here is probably
"works with exceptions and RTTI disabled".

The next two paragraphs follow the same scheme.

So in a nutshell:

The Outcome library implements a set of types to be used for lightweight
error transport.
The main features include:
  - Type safe alternative to integer or enum based error codes
  - Works with exceptions and RTTI disabled
  - Suitable for real-time and low latency applications
  - Efficient implementation
  - Rich set of different types to support different use cases

And then you can go on with everything else you want to say, possibly
with links pointing into the documentation on where potential users are
able to find more about the various topics you just advertised.
(Just a braindump of mine, not claiming this is the ultimate solution.)

>
> Niall
>

-- 
Thomas Heller
Friedrich-Alexander-Universität Erlangen-Nürnberg
Department Informatik - Lehrstuhl Rechnerarchitektur
Martensstr. 3
91058 Erlangen
Tel.: 09131/85-27018
Fax:  09131/85-27912
Email: thomas.heller_at_[hidden]

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