It's a dirty hack, but you can destroy and reconstruct yourself:
MyItemT&
MyItemT::operator=(const MyItemT& other)
{
if ( this == &other ) return *this; // "suggested" by Herb Sutter ;v)
this->MyItemT::~MyItemT();
try {
new( this ) MyItemT( other );
} catch ( ... ) {
new( this ) MyItemT(); // nothrow
throw;
}
return *this;
}
Edit: lest I destroy my credibility, I don't actually do this myself, I would remove the const
. However, I've been debating changing the practice, because const
simply is useful and better to use wherever possible.
Sometimes there is a distinction between the resource and the value represented by an object. A member may be const through changes to value as long as the resource is the same, and it would be nice to get compile-time safety on that.
Edit 2: @Charles Bailey has provided this wonderful (and highly critical) link: http://gotw.ca/gotw/023.htm.
- Semantics are tricky in any derived class
operator=
.
- It may be inefficient because it doesn't invoke assignment operators that have been defined.
- It's incompatible with wonky
operator&
overloads (whatever)
- etc.
Edit 3: Thinking through the "which resource" vs "what value" distinction, it seems clear that operator=
should always change the value and not the resource. The resource identifier may then be const
. In the example, all the members are const
. If the "info" is what's stored inside the "packet," then maybe the packet should be const
and the info not.
So the problem isn't so much figuring out the semantics of assignment as lack of an obvious value in this example, if the "info" is actually metadata. If whatever class owns a MyItemT
wants to switch it from one packet to another, it needs to either give up and use an auto_ptr<MyItemT>
instead, or resort to a similar hack as above (the identity test being unnecessary but the catch
remaining) implemented from outside. But operator=
shouldn't change resource binding except as an extra-special feature which absolutely won't interfere with anything else.
Note that this convention plays well with Sutter's advice to implement copy construction in terms of assignment.
MyItemT::MyItemT( MyItemT const &in )
: mMyPacket( in.mMyPacket ) // initialize resource, const member
{ *this = in; } // assign value, non-const, via sole assignment method