Boost logo

Boost :

Subject: Re: [boost] [outcome] comments on Regular ops
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2018-01-22 15:17:51


2018-01-22 15:53 GMT+01:00 Niall Douglas via Boost <boost_at_[hidden]>:

> > My recommendation would be not to provide comparison operators if either
> > `T` or `EC` does not provide them.
>
> Agreed. Logged to https://github.com/ned14/outcome/issues/107
>
> > The trick with catch-reswap-rethrow assumes that `T` is more likely to
> > throw while swapping/moving than `EC`, but it might be quite the
> opposite.
> > Also, it is possible that while reswapping, another exception will be
> > thrown. In general, you cannot guarantee the roll-back, so maybe it would
> > be cleaner for everyone if you just declared that upon throw from swap,
> one
> > cannot rely on the state of `result`: it should be reset or destroyed.
>
> So, don't bother attempting to restore a valid state at all?
>

To me, restoring makes sense if you can guarantee that it succeeds. Maybe
if you do it only if `EC` is nothrow-swappable.

>
> Does everybody else agree?
>
> > Another problem is that in the noexcept() clause you are mentioning
> > is_nothrow_swappable<value_type> and is_nothrow_swappable<error_type>,
> but
> > in the implementation you might be using move constructors rather than
> > swaps. This means that for types that do not throw in swap but throw in
> > move constructor (like std::list), a throw from move constructor will
> cause
> > a call to `std::terminate`. See live example here:
> > https://wandbox.org/permlink/8jIyb0fx7U72cZSt
>
> Surely if std::is_nothrow_swappable tells lies, it is only right that
> that equals std::terminate? In other words, if the STL traits tell me
> that `swap(A, B)` does not throw, and then it throws because it's
> implemented with move constructors, that's surely not my problem?
>

No, no. This happens not inside STL, but inside `result`:
https://github.com/ned14/boost-outcome/blob/master/include/boost/outcome/detail/value_storage.hpp#L257
Inside the implementation of function `value_storage_nontrivial::swap` you
are using move construction in certain cases. And this move constructor of
`T` can potentially throw and may be declared `noexcept(false)`, but you
will not see it if you are only querying for noexcept swap on `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