cplusplus / draft

C++ standards drafts
http://www.open-std.org/jtc1/sc22/wg21/
5.69k stars 748 forks source link

[intro.object]: the term "subobject" should consistently be either transitive or intransitive #2310

Open languagelawyer opened 6 years ago

languagelawyer commented 6 years ago

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?':

I think it depends on the context of the use, sadly. Strictly, subobject is not transitive, and an object is only a subobject in at most one way (it cannot be both an array element and a base class subobject, for instance), notwithstanding that a virtual base class subobject can be a subobject of multiple objects at once. Most uses of the term seem to use it in that way.

However, there are some uses that clearly intend to take the transitive closure:

  • [basic.stc.dynamic.safety]/2.2 intends to allow transitive subobjects (but should probably allow all objects nested within the original object)
  • [basic.types]/3's example says "subobject" but presumably means something more general
  • [basic.type.qualifier]/1.1, /1.2, /1.3 have ambiguous antecedents and could be reworded to make it clearer that they are transitive ("of such an object" -> "of a const object").
  • [basic.start.static]/2 intends to allow transitive subobjects
  • [conv.ptr]/3 intends to allow anything in the transitive closure of "base class subobject of". ... and so on. (I'm sure you can find more.)

Feel like filing an editorial issue? We should aim to use the term consistently.

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?)

jensmaurer commented 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).

languagelawyer commented 6 years ago

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.

jensmaurer commented 5 years ago

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".

jensmaurer commented 5 years ago

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.)