Open languagelawyer opened 6 years ago
Before we go on a voyage to fix the wording, we need a good phrasing for the various cases. It seems that [intro.object] p2 is pretty unambiguous that its definition of "subobject" is non-transitive. There is some low-hanging fruit here that just requires minor tweaks (e.g. [basic.type.qualifier] p1 bullets).
One nasty sub-case is [except.ctor] p3 and [class.copy.ctor] p10.3 (and similar places like that). The trouble here is that subobjects in the class case means base classes and non-static data members. But if a non-static data member is an array, we're not actually interested in the array type, but in the element type to figure out e.g. recursive constructor calls. And we sometimes get that right ("or array thereof" in [class.copy.ctor] p10.1) and sometimes we don't (p10.3 missing array element types). The suggestion here is to change the definition of "potentially constructed subobject" to include "array element type" (we only need the term to inspect the type's properties, not to actually perform the initialization). Yes, that would mean a "potentially constructed subobject" might include some transitivity that a "subobject" doesn't have. But an object pointer type isn't a pointer to object type, either. @zygoloid, I need your buy-in for that approach before investing time in the actual edits.
For most of the other cases, I'd suggest to say "(possibly indirect) subobject" to highlight the transitivity. Is that good enough, or do we need a formal definition? Is "transitive subobject" any better? "nested within" is taken for something related, but different, regrettably.
All phrasings with "direct subobject" should drop the "direct" as redundant. I'd also favor cross-referencing [intro.object] in places where we mention "subobject" (and that have been QA'd as being correctly non-transitive).
One thing I wanted to add: prolly the intent of the [basic.life]/1 is that multidimensional arrays have non-vacuous initialization if their "basic" elements have non-vacuous initialization. https://wg21.link/cwg1284, among other things, asked to make this clear. The resolution to the whole issue was:
The lifetime of an object is a runtime property of the object. An object is said to have non-vacuous initialization if it is of a class or aggregate type and it or one of its ~members~ subobjects is initialized by a constructor other than a trivial default constructor.
It is unclear whether it was meant that the term "subobject" is transitive here or the resolution didn't address the multidimensional array question.
Editorial meeting: Which is more useful, transitive definition of subobject and say direct subobject when we mean it? Easier to use. Investigate fall-out of that approach. Transitivity comes in when a relation is established "x is a subobject of y".
This is a can of worms. Most of our uses of "base class subobject" are wrong, assuming non-transitivity.
But it starts with [intro.object], where we pretend to define member subobject and base class subobject, but that's backwards at best: It's the class definition that causes certain subobjects to exist, so we should say so. For comparison, 10.6p3 seems backwards: "The base-specifier-list specifies the type of the base class subobjects contained in an object of the derived class type." 10.6.1p4 [class.mi] has it correct and complete:
For each distinct occurrence of a non-virtual base class in the class lattice of the most derived class, the most derived object (6.6.2) shall contain a corresponding distinct base class subobject of that type. For each distinct base class that is specified virtual, the most derived object shall contain a single base class subobject of that type.
Before I go further, here are phrasing suggestions we should like or dislike:
(This tries to avoid a circular definition, which we currently have: A subobject is an array element which is a subobject.)
Also, the term "direct subobject" should be defined and/or [except.ctor]/3 should be fixed.
Richard Smith's answer to 'Is "subobject" a transitive relation?':
From me: [except.ctor]/3: If the initialization or destruction of an object other than by delegating constructor is terminated by an exception, the destructor is invoked for each of the object's direct subobjects… (Implies that subobjects can be indirect)
If the 'direct subobjects' here are '(immediate) base class subobjects' and 'member subobjects', what does it mean for members of an array type? How can a destructor be invoked for them? (Should I create another issue for this?)