检查非活动联合成员,共同的初始序列

xer*_*ros 5 c++ union language-lawyer

这个问题就是基于

考虑以下:

struct Hdr { int type; };
struct A { Hdr h; };
union Big {
   Hdr h;
   A a;
};
Run Code Online (Sandbox Code Playgroud)

并假设Big big我们知道这big.a是工会的积极成员.是否可以访问big.h.type 未定义的行为

我认为确实是UB,基于:

class.union

... [注意:为了简化联合的使用,我们做了一个特殊的保证:如果标准布局联合包含几个共享一个公共初始序列([class.mem])的标准布局结构,如果是非此标准布局联合类型的对象的静态数据成员是活动的并且是标准布局结构之一,允许检查任何标准布局结构成员的公共初始序列; 见[class.mem]. - 结束说明]

我们拥有标准布局成员结构标准布局工会但是作为的理解,共同初始序列HdrA是即使的第一个数据成员为空A的类型的Hdr.

我是对的,这是UB吗?如果没有,我误解了哪个常见的初始序列,以便big.h.type定义访问?

eer*_*ika 4

我认为你的解释没有任何错误。

根据您的引用,只有当AHdr共享一个包含 的公共初始序列时,这才是明确定义的Hdr::type

引用定义公共初始序列的规则:

[class.mem] 两个标准布局结构体 ([class.prop]) 类型的公共初始序列是声明顺序中非静态数据成员和位字段的最长序列,从每个结构体中的第一个此类实体开始结构,使得相应的实体具有布局兼容的类型......

A因此,如果和的第一个成员Hdr(即intHdr)是布局兼容类型,则它们是通用的。这是在中指定的

[basic.types] 如果 T1 和 T2 是同一类型(它们不是同一类型)、布局兼容枚举(它们不是枚举)或布局兼容标准,则两种类型 cv1 T1 和 cv2 T2 是布局兼容类型-layout类类型(只有其中一种是类类型)

由于没有一个适用,int且不Hdr与布局兼容,因此A和 的公共初始序列Hdr为空,因此不存在引用的特殊保证适用的成员。


您可以使用包装器来绕过规则的微妙之处:

union Big {
   struct {
       Hdr h;
   } w;
   A a;
} big;
Run Code Online (Sandbox Code Playgroud)

在这里,big.w.h.type即使处于big.a活动状态,访问也将被明确定义。PS 匿名结构在这里可以很好地使包装器不可见。不幸的是,这些在标准 C++ 中格式不正确。