Is it legal to access private non-static first data member of a standard layout class?

78 Views Asked by At

For a standard layout class, it is legal to convert a pointer to an object of the class to a pointer to the first non-static data member of the class. Now assume that the first non-static data member happens to be a private member. Is this a legal way to modify a private data member outside class' member function?

If not, could you indicate what part of standard prevents it?

Note: The purpose here is to understand the standard better, not to do this in actual code.

1

There are 1 best solutions below

3
Ted Lyngmo On BEST ANSWER

"assume that the first non-static data member happens to be a private member"

That's fine, if all non-static data members are private. From the C++20 final working draft:

[basic.compound]

  1. Two objects a and b are pointer-interconvertible if:
    1. they are the same object, or
    2. one is a union object and the other is a non-static data member of that object ([class.union]), or
    3. one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, any base class subobject of that object ([class.mem]), or
    4. there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.

11.2 Properties of classes [class.prop]

  1. A class S is a standard-layout class if it:
    1. — has no non-static data members of type non-standard-layout class (or array of such types) or reference,
    2. — has no virtual functions (11.7.2) and no virtual base classes (11.7.1),
    3. has the same access control (11.9) for all non-static data members,
    4. — has no non-standard-layout base classes,
    5. — has at most one base class subobject of any given type,
    6. — has all non-static data members and bit-fields in the class and its base classes first declared in the same class, and
    7. — has no element of the set M(S) of types as a base class, where for any type X, M(X) is defined as follows.101 [Note: M(X) is the set of the types of all non-base-class subobjects that may be at a zero offset in X. — end note]
      1. — If X is a non-union class type with no (possibly inherited (11.7)) non-static data members, the set M(X) is empty.
      2. — If X is a non-union class type with a non-static data member of type X0 that is either of zero size or is the first non-static data member of X (where said member may be an anonymous union), the set M(X) consists of X0 and the elements of M(X0).
      3. — If X is a union type, the set M(X) is the union of all M(Ui) and the set containing all Ui, where each Ui is the type of the i th non-static data member of X.
      4. — If X is an array type with element type Xe, the set M(X) consists of Xe and the elements of M(Xe).
      5. — If X is a non-class, non-array type, the set M(X) is empty