Defining a standard layout class in C ++ 14

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

A standard layout class is a class that:

  • (7.1) - does not have non-static data elements such as a non-standard layout class (or an array of such types) or a link,
  • (7.2) - does not have virtual functions (10.3) and virtual base classes (10.1),
  • (7.3) - has the same access control (section 11) for all non-static data,
  • (7.4) - does not have base classes of non-standard layout,
  • (7.5) - either does not have non-static data elements in the derived class itself and no more than one base class with non-static data elements or there are no base classes with non-static data elements and
  • (7.6) - does not have base classes of the same type as the first non-static data.

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

In other words, are the non-static data members of the base class as well as the non-static data members of the derived class itself?

+5
source share
1 answer

Yes, this is a defect in C ++ 14, in particular CWG 1813 . Although you can recover it by reading the "non-static data members" to refer only to direct (non-inheritable) non-static data members (as this is probably needed elsewhere), the fix you choose should replace the language you are experiencing with the following:

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

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

It is a little hard to do right; There is some resistance to the idea of ​​treating inherited members as members of a derived class, although [class.derived] has:

[...] If no table of contents is specified in the derived class, members of the base class are also considered members of the derived class. Members of the base class, in addition to constructors, are called inherited derived classes. [...]

Despite this, in a number of places where it is assumed that both direct and inherited non-static data members will be considered as specifically invoking inherited data elements, for example, also in [class] (after permission of CWG 1672 ):

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

Or in [basic.lval] :

7.8. If X is a type of nonunit class, then the set M (X) is empty, if X does not have (possibly inherited (item 10)) non-static data; [...]

Meanwhile, in many places, “members” should be read as relevant only to direct members in order to make sense; for starters and only for viewing non-static data elements (not for 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 must have a “direct” prefix.

On the other hand, in some places (for example, in a modified [class] or in [class.copy] /23.2-23.3,/28), "members" are implicitly accepted to include inherited elements, so this is a bit of a mess.

+8
source

Source: https://habr.com/ru/post/1257818/


All Articles