Subject: Re: [boost] [outcome] Exception safety guarantees
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2017-05-28 22:36:15
2017-05-28 2:10 GMT+02:00 Peter Dimov via Boost <boost_at_[hidden]>:
> Andrzej Krzemienski wrote:
> My first reaction to this is: such a code is again fishy, ...
> That may be so, but it changes not the fact that there is the basic
> guarantee, the standard library offers it because Dave, and then there's
> the destroy-only guarantee, which the standard library does not use.
Ok, I will agree to this statement provided that you agree that "only
destroy or reset" is equivalent to basic guarantee when the invariant is
super-wide. I think we are agreeing here. I also acknowledge that the STL
requires of T's that after move they are in "vaid but unspecified state".
> You are not the only person who feels that destroy-only is better, but
> this doesn't really matter here.
If the subject of the argument is the formal definition of basic guarantee,
then agreed, my preference is irrelevant. But what interests me most what
is the optimum guarantee for `expected` and `outcome` in the context ot
this library review. And in this case my opinion is relevant to Niall or
Vicente, even if it is incorrect.
> (It's the same for move, by the way. There are people who prefer
> destroy-only for moved-from objects. The standard library does not agree
> with them, this time because Howard.)
Acknowledged. But what do the STL containers/algorithms do with the
moved-from objects other than to destroy them or reset them?
> I realize that I'm a bit curt, so here's some explanation.
> Under the destroy-only guarantee, all your member functions have a
> precondition on valid(), assuming that you even have such an accessor (of
> you don't, it's even worse). Most of the time, this doesn't matter,
> because, as you assume, you'll never encounter invalid objects. Except when
> you do.
I understand this. But exactly the same observation is to be made for all
move-only RAII classes that wrap resource handling. Once you have moves,
you get the moved-from state, and hence every member function has a weak
invariant: you have to check if it represents not-a-resource. Take
std::fstream for instance. And we are using these types and recommend using
them. And people do not put defensive if-s anywhere. Some do, but this also
isn't a good solution.
> So you have to split your code into two categories: functions that will
> never be called on invalid objects, and functions that can. You then need
> to make sure that first category functions are never, directly or
> indirectly, called during stack unwinding, either from a catch block, or
> from a destructor.
Yes, as with movable objects.
> This is possible in principle, even though it's not very reliable, because
> "never happen" objects, well, never happen, and therefore you often aren't
> testing the scenarios in which they happen. So when they do happen, it's in
But in the context of concern you are describing, valueless_by_exception is
no different than the moved-from state. moved-from state is "safe" on
`std::vector` but not on `std::fstream`. We are facing this problem in amny
> Under the basic guarantee, when your member functions don't have a "valid"
> precondition because objects are always valid, and when functions taking
> objects don't need to be split into two categories, some that can only take
> valid objects, and others that can take invalid ones, the world is simply a
> better place.
With move semantic world is not this good place any more. You have
moved-from states potentially everywhere. And this is smething we are used
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk