Boost logo

Boost :

Subject: Re: [boost] [outcome] Exception safety guarantees
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2017-05-28 22:51:21


2017-05-28 12:59 GMT+02:00 Niall Douglas via Boost <boost_at_[hidden]>:

> > I'll ask the same I asked Peter, because I no longer see the value in
> > never-empty guarantee.
> >
> > If I have two objecte of type variant<A, B, C>, where A, B can throw on
> > copy/move, and C is trivial:
> >
> > ```
> > variant<A, B, C> a = A{}, b = B{};
> >
> > try {
> > a = b; // throws
> > }
> > catch(...) {}
> >
> > // at this point a holds a C
> > ```
> >
> > What good does it make to me that I had an A, wanted to assign a B and
> got
> > a C?
>
> Why would you get a C in 'a'?
>
> 'a' previously was set to A.
>
> The assignment of 'b' with B state to 'a' failed due to exception.
>

I am describing `boost::variant` which tries to provide both "never-empty"
guarantee and "no double storage" guarantee. But it does not provide the
strong guarantee:
In short, if you assign to a, first the A is destroyed, second, we attempt
to copy-construct a B. It fails: we have no A (already destroyed) and no B
(construction failed), so it will default-construct a C, because this is
guaranteed not to throw. So the never-empty guarantee is preserved, but you
get some other value, you have no use for.

This is documented here:
http://www.boost.org/doc/libs/1_64_0/doc/html/variant/design.html#variant.design.never-empty

>
> 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.

Regards,
&rzej;

>
>


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