Please consider the following code snippet:
struct A { int n; };
struct B : A {};
B foo;
new (&foo) B { {42} }; // the new B transparently-replaces foo
int i = foo.n; // is this valid? Does this correctly refer to the new B's A.n ?
According to [basic.life] p8, the new B should transparently replace foo. However, the new B's A-subobject should not transparently replace foo.A because it is a "potentially-overlapping subobject", being a base class subobject.
However, is it enough for the enclosing B to be replaced for this to be valid?
I have two possible interpretations:
[basic.life] p8 says that
[...] the name of the original object will automatically refer to the new object [...]
thus, foo now refers to the new B.
[expr.ref] p6.2 says the following about the .-member access expression:
If
E2is a non-static data member [...] the expression [E1.E2] designates the corresponding member subobject of the object designated by the first expression.
Therefore foo.n should refer to the new foo's n.
The other interpretation is that foo.n is itself, as a whole, considered the "name of the original object" as in the wording (see above) of [basic.life], and it therefore does not refer to the new int because that int itself is not transparently-replaceable, because its encompassing object, the A, is not transparently-replaceable.
Which of these interpretations might be correct, if any?
Please keep in mind that this is a language-lawyer question. The question is not so much about whether this practically works, but about the "letter of the law" of the standard.
The first interpretation is correct. In the example:
B foois transparently replaceable by the new object of typeBcreated in its storage, since all requirements in [basic.life] p8 are met. Therefore, the name of the objectfoonow refers to the new object, and:Why the second interpretation is invalid
foo.ncan't be considered a name; it is an expression combining multiple names. I don't believe "name" is formally defined by the standard, but the word is strongly associated with identifier, as can be seen in [lex.name]. The way it's used in [dcl.pre] p4 suggests that at mostx,x::y, or...x::ycould be considred names.Regardless of what a name is,
n(i.e.A::n) is not an object, it is a non-static data member. You can also writefoo.A::nwhich makes this more obvious, and is equivalent. [expr.ref] p6.2 definesE1.E2for an object expressionE1and a non-static data memberE2.Conclusion
The transparent replacement is valid.
A::nis not transparently replaceable, but this is okay, because you replaceBas whole, and then look upA::nwithin the replacedB.The subobjects of of
foodon't have to be individually transparently-replaceable for this to be possible.