No, this is not permitted. The relevant C++ standard section is §7.6.1.10. From the first paragraph, we have (emphasis mine)
The result of the expression reinterpret_cast<T>(v)
is the result of converting the expression v
to type T
.
If T
is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if T
is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue and the lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed on the expression v
.
Conversions that can be performed explicitly using reinterpret_cast are listed below.
No other conversion can be performed explicitly using reinterpret_cast.
So unless your use case is listed on that particular page, it's not valid. Most of the sections are not relevant to your use case, but this is the one that comes closest.
An object pointer can be explicitly converted to an object pointer of a different type.[58]
When a prvalue v
of object pointer type is converted to the object pointer type “pointer to cv T
”, the result is static_cast<cv T*>(static_cast<cv void*>(v))
.
So a reinterpret_cast
from one pointer type to another is equivalent to a static_cast
through an appropriately cv-qualified void*
. Now, a static_cast
that goes from T*
to S*
can be acceptably used as a S*
if the types T
and S
are pointer-interconvertible. From §6.8.4
Two objects a and b are pointer-interconvertible if:
- they are the same object, or
- one is a union object and the other is a non-static data member of that object ([class.union]), or
- one is a standard-layout class object and the other is the first non-static data member of that object or any base class subobject of that object ([class.mem]), or
- there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.
If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_cast ([expr.reinterpret.cast]).
[Note 4: An array object and its first element are not pointer-interconvertible, even though they have the same address.
— end note]
To summarize, you can cast a pointer to a class C
to a pointer to its first member (and back) if there's no vtable to stop you. You can cast a pointer to C
into another pointer to C
(that can come up if you're adding cv-qualifiers; for instance, reinterpret_cast<const C*>(my_c_ptr)
is valid if my_c_ptr
is C*
). There are also some special rules for unions, which don't apply here. However, you can't factor through arrays, as per Note 4. The conversion you want here is quad[] -> quad -> int -> int[]
, and you can't convert between the quad[]
and the quad
. If quad
was a simple struct that contained only an int
, then you could reinterpret a quad*
as an int*
, but you can't do it through arrays, and certainly not through a nested layer of them.
None of the sections I've cited say anything about alignment. Or size. Or packing. Or padding. None of that matters. All your static_assert
s are doing is slightly increasing the probability that the undefined behavior (which is still undefined) will happen to work on more compilers. But you're using a bandaid to repair a dam; it's not going to work.