Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Definition of standard-layout class in C++14

A standard-layout class is defined in [class]/7 in C++14, as follows (emphasis is mine):

A standard-layout class is a class that:

  • (7.1) — has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • (7.2) — has no virtual functions (10.3) and no virtual base classes (10.1),
  • (7.3) — has the same access control (Clause 11) for all non-static data members,
  • (7.4) — has no non-standard-layout base classes,
  • (7.5) — 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
  • (7.6) — has no base classes of the same type as the first non-static data member.

My concern is in relation to bullet (7.5): how is it possible to have no non-static data members in the most derived class and at the same time having one base class with non-static data members?

In other words, aren't the non-static data members of the base class, also non-static data members of the most-derived class?

like image 269
Alexander Avatar asked Oct 06 '16 19:10

Alexander


People also ask

What is trivial in C++?

When a class or struct in C++ has compiler-provided or explicitly defaulted special member functions, then it is a trivial type. It occupies a contiguous memory area. It can have members with different access specifiers.

What is POD type C++?

POD is an acronym in C++ that means plain old data. It is a class/struct that ONLY has member variables and no methods, constructors, destructors, virtual functions, etc.

What is a trivial type?

A trivial type is a type whose storage is contiguous (trivially copyable) and which only supports static default initialization (trivially default constructible), either cv-qualified or not. It includes scalar types, trivial classes and arrays of any such types.


1 Answers

Yes, this is a defect in C++14, specifically CWG 1813. Although it can be repaired by reading "non-static data members" to refer only to direct (non-inherited) non-static data members (as is probably necessary elsewhere), the chosen fix has been to replace the language you found problematic with the following:

A standard-layout class is a class that: [...]

  • has all non-static data members and bit-fields in the class and its base classes first declared in the same class, [...]

This is a little tricky to get right; there is some resistance to the idea of considering inherited members as members of the derived class, even though [class.derived] has:

[...] Unless redeclared in the derived class, members of a base class are also considered to be members of the derived class. Members of a base class other than constructors are said to be inherited by the derived class. [...]

Notwithstanding this, a number of places where both direct and inherited non-static data members are intended to be considered specifically call out inherited data members, for example also in [class] (after the resolution to CWG 1672):

8.6 - an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic data members (including, recursively, an element or non-static data member of a subaggregate or contained union),

Or in [basic.lval]:

7.8 - If X is a non-union class type, the set M(X) is empty if X has no (possibly inherited (Clause 10)) non-static data members; [...]

Meanwhile, in many places "members" has to be read as referring only to direct members to make sense; to begin with and only looking at non-static data members (not member functions), [expr.rel]/3.2, [expr.const]/5.1, [dcl.constexpr]/4.6, [class.mem]/17, /19, [special]/5, [class.ctor]/4.3, /4.4, /4.10, /4.12, [class.dtor]/5.6, [class.base.init]/2, /13.3, [class.copy]/12.2, /12.4, /18.2, /25.2, /25.4, /26.3, /27, [except.spec]/15.1.1.1, /15.2, /15.3 are all places where "non-static data members" could or should have "direct" prefixed.

On the other hand, in some places (e.g. in the amended [class], or in [class.copy]/23.2-23.3, /28) "members" is implicitly taken to include inherited members, so it's a bit of a mess.

like image 141
ecatmur Avatar answered Oct 20 '22 23:10

ecatmur