|
Boost : |
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
> production.
>
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
many places.
>
> 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
to.
Regards,
&rzej;
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk