|
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