这个 std::array 的并集的公共初始序列有问题吗?

Is there a problem with common initial sequence with this union of std::array's?

是否对 Guillaume Racicot 的评论 . Is there a problem with common initial sequence 感到困惑?至少对于 GCC 10.1 x86-64 (-O3 --std=c++20 -pedantic -Wall -Werror) 我写 .words 并阅读 .bytes.

sizeof(MyUnion)==32也很安心

union MyUnion {
    static constexpr std::size_t size = 32;

    using byte = std::uint8_t;
    using word = std::uint32_t;
    
    std::array<byte, size> bytes;
    std::array<word, size / sizeof(word)> words;
};
static_assert(sizeof(MyUnion)==32);

标准说:

[array.overview]

... An array is a contiguous container. ...

An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T.

array<T, N> is a structural type if T is a structural type.

标准没有明确说明成员 std::array 有什么。因此,我们在技术上不能假设它具有任何类型的公共初始序列。

根据显示的对 std::array 的要求,我们可以合理地假设它具有 T[N] 类型的成员。如果这个假设是正确的,让我们来探讨一下是否存在一个共同的初始序列。

[class.mem.general]

The common initial sequence of two standard-layout struct ([class.prop]) types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that corresponding entities have layout-compatible types, ...

[basic.types.general]

Two types cv1 T1 and cv2 T2 are layout-compatible types if T1 and T2 are the same type, layout-compatible enumerations, or layout-compatible standard-layout class types.

std::uint8_t[32]std::uint32_t[8] 不是同一类型(忽略 cv 限定符),它们也不是枚举,也不是 类。因此它们不是布局兼容的类型,因此它们不能属于同一公共初始序列。

结论:不,我们是否可以安全地假设std::array的成员,没有共同的初始序列。


I write .words and read .bytes

程序的行为未定义。

鉴于您想将其作为(无符号)字符数组读取,重新解释而不是联合双关语是安全的:

static constexpr std::size_t size = 32;
using word = std::uint32_t;
std::array<word, size / sizeof(word)> words {
    1, 2, 3, 4,
};
std::uint8_t* bytes = reinterpret_cast<std::uint8_t*>(words.data());

而且,如果你想要一个范围:

std::span<std::uint8_t, size> bytes_range {
    bytes, bytes + size,
};