Boost logo

Boost :

From: Andrey Semashev (andysem_at_[hidden])
Date: 2007-08-23 13:46:23


Hello Maxim,

Thursday, August 23, 2007, 10:17:18 AM, you wrote:

> Hi Andrey,

> Andrey Semashev <andysem <at> mail.ru> writes:

>> I can. But this is a burden since it should be done for almost all
>> args I ever pass to ScopeExit. And I can easily forget to do so and
>> get subtle errors I pointed out before. So this is by no way should be
>> the default behavior.

> Let's look at your example.

[snip]

> First of all, even while you state:
>> the only exception to this is the "commit/dispose" flag. Playing otherwise
> may lead to subtle errors.

> In your case my_set should be also sent be reference, and if it's passed by
> value, you'll get the mentioned subtle errors (you will delete from the copy of
> the set, and the original set will be unchanged).

> So you're just switching from one set of subtle errors to another one.

I'm not switching to any other errors if I have to specify explicitly
whether the given argument is passed by reference or value.

> But additionally to this another set of subtle errors you also break strong
> exception guarantee.

I'm not, if I know that the copied objects don't throw on ctor.
Container iterators are common example of such.

> However, there are cases when copy ctor can fail, but assignment (or some other
> form of initialization/copying) can't (for example, ctor of std::vector can
> throw, but if you created and reserved enough memory successfully, assignment
> will not throw as there is no allocation).
> So you need to create a temporary object before the insertion, and then
> initialize it in some no-throw fashion.

In this particular case I would, of course, try to do as you propose.
But I can't that the case is common (at least, in my practice).

> To conclude, I don't think it worth to make default an option that breaks
> strong exception guarantee, if there is one that doesn't.

I'm still not convinced. Once again, I did not advocate to pass
arguments by value as a default library behavior. Making scope guards
actually exception-safe is a tricky task and I tend to think it's not
the place to introduce _any_ default and non-obvious behavior. Up to
this moment I like the syntax that Alexander proposed, specifically:

BOOST_SCOPE_EXIT( byref(r) byval(v) )

or any variation of such, including Steven's proposal:

BOOST_SCOPE_EXIT((cref c)(ref r)(val v))

-- 
Best regards,
 Andrey                            mailto:andysem_at_[hidden]

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