I am trying to learn about static_cast
and reinterpret_cast
.
If I am correct the standard (9.2.18) says that reinterpret_cast
for pod data is safe:
A pointer to a POD-struct object, suitably converted using a
reinterpret_cast
, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [ Note: There might therefore be unnamed padding within a POD-struct object, but not at its beginning, as necessary to achieve appropriate alignment. — end note ]
My question is how strictly to interpret this. Is, for example, layout-compatibility enough? and if not, why not?
To me, the following example shows an example where a strict 'only POD is valid' interpretation seems to be wrong.
class complex_base // a POD-class (I believe)
{
public:
double m_data[2];
};
class complex : public complex_base
{ //Not a POD-class (due to constructor and inheritance)
public:
complex(const double real, const double imag);
}
double* d = new double[4];
//I believe the following are valid because complex_base is POD
complex_base& cb1 = reinterpret_cast<complex_base&>(d[0]);
complex_base& cb2 = reinterpret_cast<complex_base&>(d[2]);
//Does the following complete a valid cast to complex even though complex is NOT POD?
complex& c1 = static_cast<complex&>(cb1);
complex& c2 = static_cast<complex&>(cb2);
Also, what can possibly break if complex_base::m_data
is protected (meaning that complex_base
is not pod)? [EDIT: and how do I protect myself/detect such breakages]
It seems to me that layout-compatibility should be enough - but this does not seem to be what the standard says.
EDIT: Thanks for the answers. They also helped me find this, http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm
You are wrong.
d[0]
does not refer to the first member of acomplex_base
object. Its alignment may therefor not be good enough for acomplex_base
object, therefor such a cast is not safe (and not allowed by the text you quote).cb1
andcb2
do not point to subobjects of an object of typecomplex
, therefor thestatic_cast
produces undefined behavior. Refer to 5.2.9p5 of C++03It's not enough if merely the types involved fit together. The text talks about a pointer pointing to a POD-struct object and about an lvalue referring to a certain subobject. oth complex and complex_base are standard-layout objects. The C++0x spec says, instead of the text you quoted:
Is POD-ness requirement too strict?
This is a different question, not regarding your example code. Yes, requiring POD-ness is too strict. In C++0x this was recognized, and a new requirement which is more loose, "standard-layout" is given. I do think that both
complex
andcomplex_base
are standard-layout classes, by the C++0x definition. The C++0x spec says, instead of the text you quoted:I interpret that as allowing to cast a pointer to a
double
, which actually points to acomplex
member (member by inheritance), to be casted to acomplex*
. A Standard-layout class is one that either has no base classes containing non-static data, or has only one base-class containing non-static data. Thus there is an unique "initial member".