Boost logo

Boost :

Subject: Re: [boost] [outcome] Change semantics on UB from peer review agreed semantics?
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2018-09-13 07:37:29


> There is first the important issue to be clear about. Should "value on
> valueless" be considered a programmer error, or a correct action? My
> *impression* of the first review was that most of the people were of
> opinion that this is a programmer bug and the controversy was about whether
> it should cause a language-level UB or be nonetheless be reported via an
> exception. But this may be just my impression.

That is my recollection as well.

> Under this impression, it was my understanding that in order to propose a
> compromise solution for the impasse Niall added the policies that determine
> if "value on valueless" is an exception or an UB. But since the throwing
> policies now guarantee to throw, no-one can tell to the programmers "you
> are using value on valueless incorrectly", because for throwing policies
> the result is well defined.

It wasn't a compromise. Original Outcome v1 was entirely wide contract,
indeed that was part of why it was rejected. People felt it should not
be wide contract by default. So, as per peer review feedback, v2 became
narrow contract by default, with carve outs for specific trait matched
categories of E type, namely `error_code` and `exception_ptr`.

Boost was then happy (ish) with v2 and its narrow-by-default contract,
and it was accepted. That's why I felt it was important that if we're
going to change this, it needs to be brought here first. This decision
was part of why v1 was rejected, and v2 was accepted. It's a non-trivial
change to the outermost presented convenience API, namely `result<T, E>`.

> I suppose the motivation behind the semantics of the default
> value-on-valueless policy was that for the semi-experienced users, who know
> that they can also control the `EC` type we do not want to expose the
> knowledge the third parameter (the policy) yet, so we choose the default
> action. But as it is easy to figure out what type of exception to throw for
> `std::error_code` (it is std::system_error), you cannot guess it for
> `MyErrorType`, so the default in that case was not to throw but cause the
> UB. But I think failure to compile is even better: we are clear to the user
> that no good default can be chosen.
>
> I am actually proposing something slightly different to what Niall
> described. if `EC` is `void` I would also go for fail-to-compile.

I should also add that any serious user of Outcome doesn't use the
default `result<T, E>`. They typedef `basic_result<T, E, Policy>` into a
namespace-local custom `result<T, E>`. The tutorial says to do this, and
the userbase is clearly doing this.

So default `result<T, E>` is really only ever used by those playing with
the library, or for trivial or toy applications. It's the "plaything"
`result<T, E>`.

That's why I'm personally minded to agree with Andrzej's proposal. The
"training wheels toy type" probably ought to hold their hand, not blow
their hand off.

Niall


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