|
|
Hello everyone,
http://www.gotw.ca/gotw/059.htm
The reason why we can not write an exception safe copy assignment for class Widget, is because (suppose we assign t1_, then assign t2_) if T1::operator=() does not throw exception, and T2::operator=() throws exception, then since all operations on T1 may throw, it means we can not find any operations on T1 which could rollback the original status to T1 without exception thrown (if exception is thrown during rollback, means rollback is not successful, and T1 will be in an in-consistent status which is different from original status -- which violates the strong exception safe guideline).
My understanding correct?
I quote the related paragraph below as well.
--------------------
3. Consider the following class:
class Widget
{
private:
T1 t1_;
T2 t2_;
};
Assume that any T1 or T2 operation might throw. Without changing the structure of the class, is it possible to write a strongly exception-safe Widget::operator=( const Widget& )? Why or why not? Draw conclusions.
Short answer: In general, no, it can't be done without changing the structure of Widget.
In the Example 3 case, it's not possible to write a strongly exception-safe Widget::operator=() because there's no way that we can change the state of both of the t1_ and t2_ members atomically. Say that we attempt to change t1_, then attempt to change t2_. The problem is twofold:
1. If the attempt to change t1_ throws, t1_ must be unchanged. That is, to make Widget::operator=() strongly exception-safe relies fundamentally on the exception safety guarantees provided by T1, namely that T1::operator=() (or whatever mutating function we are using) either succeeds or does not change its target. This comes close to requiring the strong guarantee of T1::operator=(). (The same reasoning applies to T2::operator=().)
2. If the attempt to change t1_ succeeds, but the attempt to change t2_ throws, we've entered a "halfway" state and cannot in general roll back the change already made to t1_.
--------------------
thanks in advance,
George
|
|
|
|
|
George_George wrote: My understanding correct?
Maybe. I can't tell what it is you think you understand. The entire concept seems incredibly obvious to me. Anyone else?
led mike
|
|
|
|
|
Thanks led mike,
What I do not understand and also the quoted paragraph is not clear is about "cannot in general roll back the change already made to t1_.". Why can not rollback in general? Because of exception occurs in rollback operation of t1_?
regards,
George
|
|
|
|
|
George_George wrote: The reason why we can not write an exception safe copy assignment for class Widget, is because (suppose we assign t1_, then assign t2_) if T1::operator=() does not throw exception, and T2::operator=() throws exception, then since all operations on T1 may throw, it means we can not find any operations on T1 which could rollback the original status to T1 without exception thrown (if exception is thrown during rollback, means rollback is not successful, and T1 will be in an in-consistent status which is different from original status -- which violates the strong exception safe guideline).
You're interpretation is correct, but is not the whole scenario: it maybe also impossible to roll back because T1 class public interface simply doesn't allow it.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
Thanks CPallini,
CPallini wrote: it maybe also impossible to roll back because T1 class public interface simply doesn't allow it.
To rollback, we can simply make assignment again. If we keep the original object's status into a temp object. I do not agree with you there is no public interface -- assignment is enough.
Any comments?
regards,
George
|
|
|
|
|
George_George wrote: To rollback, we can simply make assignment again.
What? And the user is going to know about this rollback how? Did I wake up in an alternate dimension this morning? Has anyone here read Meyers? Have I completely misremembered his entire point on operators?
led mike
|
|
|
|
|
<br />
try<br />
{<br />
temp = this->tx;<br />
this->tx = rhs.tx;<br />
}<br />
catch (...)<br />
{<br />
this->tx = temp;
throw;<br />
}<br />
The problem here is that the rollback operation might throw, too.
We are a big screwed up dysfunctional psychotic happy family - some more screwed up, others more happy, but everybody's psychotic joint venture definition of CP blog: TDD - the Aha! | Linkify!| FoldWithUs! | sighist
|
|
|
|
|
Hi led mike,
Then, how do you understand the statement "cannot in general roll back the change already made to t1_", why can not?
regards,
George
|
|
|
|
|
George_George wrote: the statement "cannot in general roll back the change already made to t1_", why can not?
I don't care why can't since you shouldn't anyway. It would be "bad practice" to do something like that (rollback) in an assignment operator because the user will not expect that outcome which then leads to errors that are difficult to locate. Again I highly recommend anyone that aspires to be more than a junior C++ developer reads Meyers Effective C++ books. The material he covers is far more valuable than knowing which register they keep the stack pointer in or how the VTable works.
led mike
|
|
|
|
|
Hi led mike,
If there is exception thrown in assignment operator, how do you ensure exception safety -- making all objects in consistent status without using rollback? Could you describe a solution with some pseudo code please? Refer a link to save typing is also fine.
regards,
George
|
|
|
|
|
George_George wrote: If there is exception thrown in assignment operator
Then don't do one. If you can't perform the activities required in an assignment operation without the possibility of an exception, then override the assignment operator as private to keep anyone from using it and implement the feature as a method. The method name should be descriptive like "Copy" or "SafeCopy" or something and would then be appropriate to perform any sort of operation you want with documentation of the pre/post conditions and alternate outcomes. In rare and unavoidable cases it is even appropriate for the documentation to state that in the case of an exception the state of the object is unknown.
When a user sees the method name "SafeCopy" he should be interested in reading the documentation to discover exactly what that means. This is not true for an assignment operator which carries an implicit contractual meaning.
led mike
|
|
|
|
|
I got your points, led mike!
regards,
George
|
|
|
|
|
George_George wrote: assignment is enough.
What if it throws again?
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
Thanks CPallini,
Do you mean if assignment throws, we need some other public method from the class which could do rollback job without throwing again?
regards,
George
|
|
|
|
|
Yes and probably we haven't that option.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
Why "probably", CPallini?
I quote what you said, and you should be sure about what you mean.
regards,
George
|
|
|
|
|
George_George wrote: Why "probably", CPallini?
It depends on T1 public interface, we don't know about.
George_George wrote: I quote what you said, and you should be sure about what you mean.
If you quote my words, you should include "that is going on his arrogant assumptions..."
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
Thanks CPallini,
Makes senses.
regards,
George
|
|
|
|
|
Since when is rolling back an inherent feature of an assignment operator? I don't remember seeing that in Effective C++ or anywhere else.
led mike
|
|
|
|
|
I think he means a logical concept of "rollback", i.e. keep the status of object consistent (e.g. original).
regards,
George
|
|
|
|
|
rollback is not consistent with the implied contract of an assignment. At least I'm pretty sure it isn't on the plant I come from. I'm not really sure where I am at this moment.
Have you read Meyers?
led mike
|
|
|
|
|
led mike wrote: At least I'm pretty sure it isn't on the plant I come from
Nuclear plant?
led mike wrote: Have you read Meyers?
Nope, chemistry [^] is not my favourite topic.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
Thanks led mike,
Then, how do you understand the statement "cannot in general roll back the change already made to t1_", why can not?
regards,
George
|
|
|
|
|
led mike wrote: is rolling back an inherent feature of an assignment operator
Who said that?
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|