使用std::array的这种并集的公共初始序列是否存在问题?



对Guillaume Racicot的评论感到困惑。这里有公共初始序列的问题吗?至少在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]

…数组是一个连续的容器. ...

数组是一个集合,可以用最多N个元素进行列表初始化,这些元素的类型可转换为t

如果T是结构类型,则array<T, N>是结构类型

标准没有明确说明std::array有哪些成员。因此,从技术上讲,我们不能假设它具有与任何类型相同的初始序列。

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

[class.mem.general]

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

[basic.types.general]

如果T1和T2是相同的类型,cv1 T1和cv2 T2是布局兼容的类型,或者是布局兼容的枚举,或者是布局兼容的标准布局类类型。

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

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


我写。words和读。bytes

程序的行为未定义。

如果您希望将其作为(unsigned) char数组读取,则重新解释而不是联合双关语将是安全的:

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,
};

最新更新