"GotW #28" is an old article written by Herb Sutter. In that article, Herb explains why the following design is a bad idea (I took the liberty to replace assert with static_assert, though):
// file y.h
class Y
{
/*...*/
static const size_t sizeofx = /*some value*/;
char x_[sizeofx];
};
// file y.cpp
#include "x.h"
Y::Y() {
static_assert( sizeofx >= sizeof(X), "Please, fix Y::sizeofx" );
new (&x_[0]) X;
}
Y::~Y()
{
(reinterpret_cast<X*>(&x_[0]))->~X();
}
Leaving aside the questions of alignment (std::aligned_storage wasn't around at the time) and maintenance, I'd like to focus on the following point:
Herb Sutter claims that writing a safe (considering exception safety) Y::operator=() and safe Y::~Y() is a lot more trouble than it's worth. And this is something I don't get.
What trouble is he talking about? What's wrong with the destructor above? And what's wrong with a simple assignment like this:
Y& Y::operator=(const Y& other)
{
*reinterpret_cast<X*>(&x_[0]) = *reinterpret_cast<const X*>(&other.x_[0]);
return *this;
}
Given that Y class has neither base classes no other members, I would say that exception guarantees of Y::operator=(const Y&) and Y::~Y() will be those of corresponding X::operator=(const X&) and X::~X(). But Herb Sutter hinted that there's more trouble to it...
What am I missing?