Home > Software design >  Confused about std::is_standard_layout type trait
Confused about std::is_standard_layout type trait

Time:10-05

Standard-layout class describes a standard layout class that:

  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 and no virtual base classes,
  3. has the same access control for all non-static data members,
  4. has no non-standard-layout base classes,
  5. has all non-static data members and bit-fields in the class and its base classes first declared in the same class, and
  6. given the class as S, has no element of the set M(S) of types as a base class, where M(X) for a type X is defined as:
    1. If X is a non-union class type with no (possibly inherited) non-static data members, the set M(X) is empty.
    2. If X is a non-union class type whose first non-static data member has type X0 (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 ith 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.

(numbered for convivence)

However, the following fails:

#include <type_traits>

struct A {
    int a;
};
struct B : A {
    int b;
};

static_assert(std::is_standard_layout<A>::value, "not standard layout"); // succeeds
static_assert(std::is_standard_layout<B>::value, "not standard layout"); // fails

Demo

I see that 1-4 are true, so is one of points under 5 false? I find the points under 5 a little confusing.

CodePudding user response:

The cppreference description is a little confusing.

The standard (search "standard-layout class is") says:

A standard-layout class is a class that:

  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • has no virtual functions (10.3) and no virtual base classes (10.1),
  • has the same access control (Clause 11) for all non-static data members,
  • has no non-standard-layout base classes,
  • either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
  • has no base classes of the same type as the first non-static data member.

You can see from the part I emphasized that a class with a non-static data member and a base class that itself has a non-static data member is not standard-layout.

I suspect this point is described as follows in cppreference:

has all non-static data members and bit-fields in the class and its base classes first declared in the same class

The point is that you must be able to cast the address of a standard-layout class object to a pointer to its first member, and back. It boils down to compatibility between C and C.

See also: Why is C 11's POD "standard layout" definition the way it is?.

  • Related