Boost logo

Boost :

Subject: Re: [boost] [outcome] Exception safety guarantees
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2017-05-29 07:41:21

2017-05-29 1:38 GMT+02:00 Niall Douglas via Boost <boost_at_[hidden]>:

> >> So the strong never empty guarantee implemented by both Outcome and
> >> Expected means that 'a' still contains its original A untouched and
> >> undamaged. 'b' also contains its B untouched and undamaged, though that
> >> is up to B's copy constructor.
> >>
> >
> > I wonder if this is possible. In `result` you have a T an an
> > error_code_extended. If you are assigning to an errored result:
> >
> > ```
> > outcome<T> o = make_errored_result(xxx);
> > outcome<T> v = T{yyy};
> >
> > o = v;
> > ```
> >
> > What do you do? First you need to destroy the error_code_extended stored
> by
> > `o`. Then you try to copy-construct T in the same storage. If it fails,
> you
> > have no error to return to: you have just destroyed it, and possibly
> > overwrote the storage.
> >
> > So I fail to see how you can implement a strong guarantee for the
> > assignment, unless you apply no-throw restrictions on type T.
> It's very straightforward.

Yes, I just realized it is, because....

> If the existing state's type is nothrow move but the new state's type is
> throwing move/copy, you move it onto the stack. Then you clear storage,
> and assign in the T. If that throws, you restore the stacked previous
> state.
> If the existing state's type is throwing move and the new state's type
> is nothrow move, you destruct, clear storage, and do the assignment.
> Only if the existing state's type is throwing and the new state's type
> is throwing is there a problem. That's why I said earlier that to
> implement the strong never empty guarantee without additional storage,
> all but one of a variant's types must be nothrow move.

Yes, and in both expected<> and outcome<> you are guaranteed that the E is
nothrow movable (and copyable). This is why you do not have the problem
that variant in the general case has.

> Does this make sense?

Yes, it does now. In that case I understand Vicente's recommendation, and I
support it: the constraint (the static_assert-s) that E is nothrow-movable
should be imposed on the copy/move-assignment, but not on the entire type.
If I am not doing assignments on `expected` there is nothing wrong in
having an E that throws upon copying. (As in my example with validating


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