【发布时间】:2018-07-25 04:46:14
【问题描述】:
我有一个标准布局联合,其中包含一大堆类型:
union Big {
Hdr h;
A a;
B b;
C c;
D d;
E e;
F f;
};
A 到 F 类型中的每一个都是标准布局,其第一个成员是 Hdr 类型的对象。 Hdr 标识联合的活动成员是什么,所以这是变体。现在,我确定(因为我检查过)活跃成员是B 或C。实际上,我已将空间缩小到:
union Little {
Hdr h;
B b;
C c;
};
现在,以下是明确定义还是未定义的行为?
void given_big(Big const& big) {
switch(big.h.type) {
case B::type: // fallthrough
case C::type:
given_b_or_c(reinterpret_cast<Little const&>(big));
break;
// ... other cases here ...
}
}
void given_b_or_c(Little const& little) {
if (little.h.type == B::type) {
use_a_b(little.b);
} else {
use_a_c(little.c);
}
}
Little 的目标是有效地充当文档,我已经检查过它是 B 或 C,所以将来没有人添加代码来检查它是 A 或其他东西。
我将B 子对象作为B 阅读这一事实是否足以使其格式正确?在这里可以有意义地使用公共初始序列规则吗?
【问题讨论】:
-
这个:“如果两个联合成员是标准布局类型,那么在任何编译器上检查它们的公共子序列都是明确定义的。” 但我认为我们需要更多信息来确定;来自:en.cppreference.com/w/cpp/language/union
-
无论如何你只需要使用
big.h.type,它已经被正式文档UB :) -
@RbMm 使用
big.h.type是合法的。 OP提到的“通用初始子序列规则”强制它。 -
@RbMm 参见here,尤其是标准布局类型的特殊属性。
-
RbMm :你做错了。您在哪里可以找到标准中的措辞,即如果两个对象具有相同的地址,那么您可以重新解释转换指针?不要只考虑一个简单的编译器实现,而是一个高度优化的编译器,它假设您的代码不会调用未定义的行为。 (OP 并没有问“它可能会工作”,而是“必须它可以在任何符合要求的编译器上工作。)
标签: c++ c++11 language-lawyer