|
Boost : |
Subject: Re: [boost] [outcome] High level summary of review feedback accepted so far
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2017-06-02 08:04:19
2017-06-02 8:57 GMT+02:00 Gavin Lambert via Boost <boost_at_[hidden]>:
> On 2/06/2017 18:45, Andrzej Krzemienski wrote:
>
>> There is a reasonable mental model behind it. But you have to forget the
>> other example (where Niall is using `result<T>` as though it were a
>> `boost::optional<T>`).
>>
>
> It does make more sense that way around.
>
> I would protest for one. You either throw from destructor of you don't
>> throw from destructor. But I do not accept that you sometimes throw and
>> you
>> sometimes don't.
>>
>
> The purpose of avoiding the throw when std::uncaught_exception() is true
> is to avoid confusing everyone with a validation error when you're already
> in the middle of an unwind (and thus the thing you were validating is
> probably uninteresting now). This also avoids clobbering the original
> exception with your new one, which makes life better for everyone.
>
> But there is a more fundamental objection to it. Unless you use destructors
>> to perform significant tasks and business logic, the normal usage of C++
>> classes is that other member function do the business logic, and
>> destructors only clean up resources. If you failed to do the business
>> logic
>> you start the stack unwinding because other people up the stack depend on
>> your having finished your part of the logic. In contrast, when you have
>> failed to release resources, people up the stack still consider your
>> business task as finished and they can work with it, and likely will not
>> use the resource you are about to waste (and even if they need it, they
>> will be informed by a throw from a constructor of other resource-handling
>> class).
>>
>
> While I agree in general, there are occasionally some interesting benefits
> from abusing destructors. One such I've seen in Google Test, where you can
> add arbitrary data to any assertion just by streaming it, eg:
>
> EXPECT_TRUE(foo(bar)) << "foo did something weird" << bar << baz;
>
> The way this works is to collect up the items into a temporary object
> which then assembles into a string and carries out the actual action in the
> destructor, which obviously can throw for several reasons.
>
> Abuse? Yes. But it enables a very nice coding syntax.
I do not mind it. You do not start evaluating your assertion when the stack
is being unwound anyway. But I would expect std::terminate if evaluating
`bar` throws and then the destructor also throws. I mean both "I accept it"
and "I prefer it".
Regards,
&rzej;
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk