Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
languagelawyer opened this issue Aug 29, 2018 · 4 comments

Comments

@languagelawyer
Copy link
Contributor

languagelawyer commented Aug 29, 2018

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

@zygoloid zygoloid changed the title [intro.object]: the "subobject" term should be transitive [intro.object]: the term "subobject" should consistently be either transitive or intransitive Aug 29, 2018
@jensmaurer
Copy link
Member

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

@jensmaurer jensmaurer added the decision-required A decision of the editorial group (or the Project Editor) is required. label Sep 4, 2018
@languagelawyer
Copy link
Contributor Author

languagelawyer commented Sep 19, 2018

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
Copy link
Member

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 jensmaurer removed the decision-required A decision of the editorial group (or the Project Editor) is required. label Nov 6, 2018
@jensmaurer
Copy link
Member

jensmaurer commented Jan 29, 2019

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:

  • Kill the quoted sentence in 10.6p3.
  • Define all sub/object things in [intro.object], i.e.
  • Move 10.6.1p4 [class.mi] there, replacing "subobject" with "object", otherwise we are circular: "most derived class" uses "complete object", which is defined as "not being a subobject".
  • Add "For each direct non-static non-reference data member of a class type C [class.mem], an object of type C contains an object of the type of the data member, called a direct member subobject."
  • Move the [dcl.array] sentence "An object of array type contains a contiguously allocated non-empty set of N subobjects of type T, called the array element subobjects."
  • And then
    A direct subobject of an object is a direct member subobject, a direct base class subobject, or an array element subobject.
    A subobject of an object is a direct subobject, or a direct subobject of a subobject of that object.

(This tries to avoid a circular definition, which we currently have: A subobject is an array element which is a subobject.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants