In C++17 there is normative text [class.mem]/17:
Non-static data members of a (non-union) class with the same access control (Clause 14) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified.
Also there is [class.mem]/24:
If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member
Here are two examples:
struct A { int x, y, z; } a;
struct F { public: int p; private: int q; public: int r; } f;
According to the above standard text, C++17 guaranteed &a.x < &a.y
, &a.y < &a.z
, and &f.p < &f.r
(but did NOT guarantee &f.p < &f.q
, since F
is not standard-layout so class.mem/24 does not apply).
However, in C++20 final working draft N4860, there has been a change as per CWG 2404. The [class.mem]/17 has been turned into a Note. However, notes are non-normative in ISO standards (meaning the compiler vendor can disregard them) . And I cannot find any other text that might apply.
My question is: does C++20 still somewhere specify (normatively) the guarantees &a.y < &a.z
and/or &f.p < &f.r
? Or does the compiler now have the licence to reorder class members in all cases except for the first subobject of a standard-layout class?
Assuming there are no further changes between N4860 and the published standard, I guess.
This is still guaranteed by [expr.rel]/(4.2), describing the behavior of built-in <
, <=
, >
, and >=
expressions on pointer values.
If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member is required to compare greater provided the two members have the same access control ([class.access]), neither member is a subobject of zero size, and their class is not a union.