Subject: Re: [boost] [outcome] How to drop the formal empty state
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2017-05-25 23:36:24
On 26/05/2017 02:30, Niall Douglas wrote:
> This is precisely why I added a formal empty state, and default
> initialised to that. Because it causes behaviour different to valued or
> errored, it **very** effectively traps logic errors during code
> development. On **many** occasions it has successfully illuminated
> poorly thought through code that I have written by bringing to my
> attention - early and very obviously - that someone was very wrong. I am
> absolutely convinced it is a great design choice.
My worry with the formal empty state is precisely that as neither a
value nor an error, someone might fail to check for it in code and then
proceed under a false assumption. (If not has_error() then this void
method must have succeeded, and I don't call value() because it was void.)
Provided that .value() and .error() both throw if called in the empty
state (which I assume is the case), that helps mitigate a large part of
that, but not entirely, as in the case above.
Yes, it's a misuse of the type, but it's one that I can see being very
likely to happen in the real world. Even if the possibility of an empty
state is heralded with bold blinking all-caps on all doc pages.
> I'd therefore be happier with default construction giving uninitialised
> contents, or a default constructed T or E. No overloading state of E.
I strongly agree with Peter Dimov that introducing uninitialized state
is a very undesirable thing. I still regard it as very rare in the
majority of codebases that sanitizers that would detect that sort of
thing would ever be run, so this would simply introduce the very type of
UB that having a formal error-handling type is intended to reduce.
I don't like the idea of a default-constructed T because T is not always
default-constructible, and this makes it inconsistently behaved for
different T and makes it harder to use uniformly in containers,
especially in generic code.
I don't like the idea of a default-constructed E because by convention
(even if not quite in fact as Niall has pointed out -- though I've yet
to see a platform where a 0 error code *didn't* mean success, other than
cases where the formal type is int but is actually used as bool) the
default-constructed error_code means "no error", and this is heavily
reinforced by its operator bool semantics.
I do like the idea of a non-default-constructed error code, because
failure to initialise the result does seem like an error to me. Niall
points out that this is harder to detect and treat specially in code but
I don't agree with that; as long as a suitably unique error code is used
then a simple assert in the error path would pick it up, no problem.
If the consensus is that an initial non-default error code is not
satisfactory, then a formal empty state seems to me like the least worst
alternative. I just know that it's going to bite someone at some point.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk