C++20“透明可替换”关系

JMC*_*JMC 11 c++ language-lawyer c++20

在 C++20 的最终工作草案(以及下面链接的最新公开可用草案)中,关于如何允许对象替换其他对象,[basic.life] 的措辞已经改变,以便指针、引用和对象的name 自动引用新对象。为此,引入了“透明可替换”的关系。但是,我不确定我是否正确理解了这一点。考虑这个例子:

struct X {int a = 3; float b;};
X x;
new(&x.a) int(5);
x.a == 5 // true without std::launder?
Run Code Online (Sandbox Code Playgroud)

在 C++17 中这当然是正确的,因为旧的 int 既不是 const 对象,也不是具有 const 非静态成员的类。

然而,现在新的透明可替换关系可能不再允许这样做了。在考虑新旧 int 对象的关系时,满足条件(8.1)到(8.4),但条件(8.5)呢?

o1 (旧的 int)和 o2 (新的 int)都是完整的对象(旧的 int 肯定是一个子对象,所以这部分是假的)或者 o1 和 o2 分别是对象 p1 和 p2 的直接子对象,而 p1可以透明地替换为 p2。

new int 是一个完整的对象,因为它是“自己”构造的(我们只放置了一个 new int 而不是一个新的 X)?

或者是否可以认为由于[intro.object]\2的措辞,新 int 是 x 的子对象,就像旧 int 一样,(我高度怀疑这是预期的解释,tbh),因此 x 满足p1 和 p2 在定义中的作用,然后 x 是否可以“透明地替换”自身,这意味着满足 (8.5) 吗?

或者即使不涉及 const 限定,现在也需要 std::launder 的意图是什么?

Ric*_*ith 4

无论 [basic.life]p8 是否适用,[intro.object]p2 都适用,因此 o1 和 o2 是同一对象的直接子对象。您可以轻松检查对象始终可以透明地自行替换,因此 p1 透明地替换 p2,因此 o1 透明地替换 o2。

这符合旨在狭隘地解决C++20 委员会草案上的国家机构评论US041 的意图。具体来说,在 [intro.object]p2 不适用的情况下(例如,因为替换的对象是基类子对象而不是数组元素或成员子对象),则无法再访问新创建的(完整)对象就好像它是另一个对象的子对象一样。