
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@mail.ru