struct Vec0
{
union { float x, r, h; };
union { float y, g, s; };
union { float z, b, v; };
};
I wanted to ask, does the C++ standard guarantee this data will be aligned exactly the same as if I wrote it
struct Vec1
{
float x, y, z;
};
The address y immediately follows the address of x plus the length for a float + padding bits/alignment (I think).
Think it does (guarantee the layout), but was curious if it is guaranteed by the ISO C++ Standard?
Update:
To clarify, I am interested in the question, is there any guarantee in the ISO C++ standard that
offsetof(Vec0, x /*or r h*/) == offsetof(Vec1, x)
offsetof(Vec0, y /*or g s*/) == offsetof(Vec1, y)
offsetof(Vec0, z /*or b v*/) == offsetof(Vec1, z)
This may fall into the category of them being layout compatible
I am also interested in the sub-case of whether or not the offset of (but not necessarily offsetof because one may not be able to use offsetof outside the struct/class/etc., perhaps except in the hypothetical were it were able to access private/protected data members outside the struct/class/etc.) each data member would be the same between the two if all their data-members were made private/protected.
Also just to note this is not a software design/architecture/best practice question, I am aware there are better ways to access these data members for most cases.
It is not, there can be any arbitrary padding between the
unionorfloatmembers that doesn't have to be consistent between the two examples. This holds in ISO standard C++ as well as ISO standard C.However, if there is no good reason to add such padding, there wouldn't be any point to it being added. The class layout is part of the ABI and therefore specified in the specification of the C++ ABI or underlying C ABI that your compilation is assuming. You can get definitive answers for your particular compiler/platform combination in the corresponding ABI specification.
After edit of question:
is guaranteed for all choices, because
Vec0andVec1are standard-layout in your example. Therefore all of of these offsets are required to be exactly0.On the other hand
are not guaranteed in any case by the C++ standard. The padding after the first (and following) members can be different between the two classes, although I don't see any good reason for the ABI to make that choice in your specific example.
Vec0andVec1are not layout-compatible. It already fails the listed requirements in your link because a single non-class member likeVec1::xcan never be layout-compatible with a (union) class member like the first anonymous union ofVec0.Note that types not being layout-compatible does not mean that their members won't have same layout. It just specifies one specific condition under which they effectively have to. The layout-compatibility condition is only relevant for one very specific usage of the class, i.e. when both appear as members of a union, in which case there is an exception to the active member rules for that union. That's the only situation in which layout-compatibility has any relevance in the language.
If not all of the members have the same accessibility (
private/protected/public), then the class stops being a standard-layout class and even the guarantee that the first members are at offset zero doesn't hold anymore.