1

I am asking the question again because the only other question that is like this is approaching 10 years old, and contains incorrect information about expressions involving base class subobjects:

[defns.dynamic.type] defines the dynamic type of a glvalue as:

type of the most derived object to which the glvalue refers

A glvalue only refers to at most one object, and since "most derived object" as defined by [intro.object] p6 essentially is:

A complete object, a data member, or an array element of class type, or, an object of a non-class type is called a most derived object.

If the glvalue does not refer to a most derived object, then would the dynamic type be undefined?

Also, I know the intended effect of dynamic type of an expression is: for a glvalue expression E that refers to an object of type B, which is a base class subobject of an object of type D, where B is a base class of D, to get the type D from E, however, I do not see how the current wording accomplishes that, or even needs to, since references/pointers of base class type bound to derived class type will always refer to the base class subobject. As far as I can tell, a case where the type of the expression and the type of the object that it refers to would never occur.

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Krystian S
  • 1,586
  • 7
  • 23
  • 1
    what is "the only other question" ? A question containing wrong information is kind of natural, what about the answers? – 463035818_is_not_an_ai Jun 28 '19 at 20:08
  • 1
    @formerly The answers are incorrect, they state that for this snippet: `const T& a = U();` the reference is bound to the object of type `U`, when infact it is bound to the base class subobject of the temporary object that is creates (assuming `U is derived from `T`) – Krystian S Jun 28 '19 at 20:17
  • @KrystianS: "*when infact it is bound to the base class subobject of the temporary object that is creates (assuming `U` is derived from `T`) *" Can you cite where that actually is said in the standard? Because that's not how references work. As far as the standard is concerned, `a` is a reference to a `U`, with the type `T`. – Nicol Bolas Jun 28 '19 at 20:31
  • 1
    @Nicol Bolas see http://eel.is/c++draft/dcl.init.ref#5 – Krystian S Jun 28 '19 at 20:34
  • Can you add a link to "the only other question"? – 1201ProgramAlarm Jun 28 '19 at 20:50
  • @1201ProgramAlarm https://stackoverflow.com/questions/7649649/what-is-dynamic-type-of-object and I like your username :) – Krystian S Jun 28 '19 at 20:53

2 Answers2

5

If the glvalue does not refer to a most derived object, then would the dynamic type be undefined?

It always does. Hence the "then" part does not apply.

Update in response to comment

Given

struct foo { };
struct bar : foo { };
const foo& a = bar(); a;

What is the dynamic type of a?

The answer is found in the page you linked to in your post:

[ Example: If a pointer p whose static type is “pointer to class B” is pointing to an object of class D, derived from B, the dynamic type of the expression *p is “D”. References are treated similarly. — end example ]

The dynamic type of a is bar, not foo.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 4
    Flashbacks to Propositional Logic 101 and material implication. – Eljay Jun 28 '19 at 20:04
  • @Eljay, I wasn't aware of the subject. Interesting subject to occupy one's grey matter. https://www.iep.utm.edu/prop-log/. – R Sahu Jun 28 '19 at 20:09
  • 1
    @R Sahu Does it? Take this for example: `struct foo { }; struct bar : foo { }; const foo& a = bar(); a; // a refers to the foo subobject of the bar temporary, so the object the glvalue refers to is not a complete object, nor a member, nor an array element, nor an object of non-class type, so how could the dynamic type be the type of the most derived object, if the object that a refers to is not one` – Krystian S Jun 28 '19 at 20:21
  • 1
    @KrystianS, in that case, the dynamic type of `a` is `bar&`. – R Sahu Jun 28 '19 at 20:25
  • 1
    @R Shau I don't think so, as dictated by [expr.type] p1, expressions that denote references are adjusted to denote the object denoted by the reference, and the type of the expression is adjusted as well. – Krystian S Jun 28 '19 at 20:27
  • @KrystianS, I am not finding that language in C++11, C++14, or C++17. Please post a link, if you have one. Thanks. – R Sahu Jun 28 '19 at 20:36
  • @KrystianS: "*expressions that denote references are adjusted to denote the object denoted by the reference, and the type of the expression is adjusted as well.*" Then explain why the [strict aliasing rule](https://timsong-cpp.github.io/cppwp/n4659/basic.lval#8.1) has an explicit allowance for accessing a derived class object through a pointer/reference to a base class? If C++ thought of references to base class subjects as identical to references to any object of that type, then there would be no need for such a provision. – Nicol Bolas Jun 28 '19 at 20:42
  • @KrystianS: [expr.type]/1 doesn't say that the reference suddenly becomes a `T` which behaves identically to any other `T`; only that the type of the reference becomes `T` rather than `T&`. – Nicol Bolas Jun 28 '19 at 20:43
  • @Nicol Bolas The reference does not change, but the expression does. Given `T& t = u;` the expression `t` will be of type `T`, and will refer denote to object denoted by `u`. – Krystian S Jun 28 '19 at 20:48
  • @KrystianS: "*The reference does not change, but the expression does.*" No, the *type* of the expression changes. The expression is still a reference; it merely has the type `T` as far as any subsequent processing goes. – Nicol Bolas Jun 28 '19 at 20:50
  • @Nicol Bolas I don't know why that exception is there, however I can tell you that when binding a reference to an object of derived class type, where the type refered to is a base class of the object being bound to, the reference is bound to the base class subobject, not the complete object of derived type. The same applies to pointers. – Krystian S Jun 28 '19 at 20:50
  • 1
    @Nicol Bolas It does change what the expression denotes, as stated here http://eel.is/c++draft/expr.type#1.sentence-2 – Krystian S Jun 28 '19 at 20:52
  • @Nicol Bolas Can we agree now that references, when bound to an object of a derived type, will bind to the base class subobject? – Krystian S Jun 28 '19 at 21:37
  • @NicolBolas Then why did the so called strict aliasing rule had an item about aggregates? Your meta argument is extremely weak. – curiousguy Jun 30 '19 at 20:20
  • It makes **no sense** to say that any ptr must points to the complete object. What would a derived to base conversion even do? Nothing? That's absurd on its face; even if the std text says so, it should be disregarded. Many times the text contained absurd statements, and never these patently false statements were allowed to shape the language. – curiousguy Jun 30 '19 at 20:31
  • @curiousguy, It makes sense to me that the dynamic type, not the static type, of the object that the pointer points to is the type of the complete object. – R Sahu Jun 30 '19 at 21:22
  • @RSahu Yes it's the dynamic type but you must admit that a ptr points to base class subobject for C++ to make sense, or there is no derived to base real conversion! – curiousguy Jun 30 '19 at 21:25
  • @curiousguy, agreed. Completely. – R Sahu Jun 30 '19 at 21:48
3

I think you might be able to argue that this is a wording defect, but it would be pedantic because the intent is already clear. Instead of:

type of the most derived object to which the glvalue refers

you might imagine that the definition reads:

type of the most derived object of the object to which the glvalue refers

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • Most derived object isn't a property of an object, but rather something that an object can be, so I don't see how that wording would make sense... Either way, I don't see a single case where the type of an expression would differ from the object it denotes. – Krystian S Jun 28 '19 at 20:25
  • @KrystianS: "*Either way, I don't see a single case where the type of an expression would differ from the object it denotes.*" Then that right there is the problem, because that's how pointers and references work in C++. You have a reference to an object. The type of that reference can be *different* from the type of the object (referencing a derived class through a reference of a base class type). But you're *always* referencing the complete object. – Nicol Bolas Jun 28 '19 at 20:27
  • 2
    @KrystianS You should interpret "the most derived object of the object" as "the unique object that is a most derived object and either is the object in question or contains it as a base class subobject". – Brian Bi Jun 28 '19 at 20:27
  • 1
    @Nicol Bolas When you bind a reference of type `B` to an object of type `D`, where `B` is a base class of `D`, the reference binds to the base class subobject of the object of type `D`, that base class subobject being the type of the base class, `B`, not the complete object of type `D`. See http://eel.is/c++draft/dcl.init.ref#5 "[...] or, in either case, to the appropriate base class subobject of the object.". The same applies to pointers, there is a standard pointer conversion that is applied, see [conv.ptr] – Krystian S Jun 28 '19 at 20:33
  • 1
    @KrystianS "_the reference binds to the base class subobject of the object of type D_" That goes w/o saying! C++ wouldn't make much sense if ptr and ref to subobjects did not actually refer to subobjects. – curiousguy Jun 30 '19 at 18:53
  • @curiousguy He didn't seem to agree :P – Krystian S Jun 30 '19 at 19:24
  • @KrystianS At some point, I say whatever the std says, ppl know intuitively what is correct. **In no case in history were the words of the std allowed to shape the reality of C++.** The intuition of ppl who know what they are talking about shape C++. The words and the committee members try to keep up with reality. Not the other way around, despite what many ppl here try to insinuate. – curiousguy Jun 30 '19 at 20:02
  • @KrystianS Did this answer fully address your question? – Brian Bi Jul 01 '19 at 14:38
  • @Brian well, in a way yes. I submitted a issue on the repo, and also wrote up some wording to fix it - hopefully I can take care of it editorially. – Krystian S Jul 02 '19 at 13:46