在不同限定的结构成员上使用 reinterpret_cast 安全吗?

Is this use of reinterpret_cast on differently-qualified struct members safe?

我查看了以下相关的问题,其中 none 似乎解决了我的确切问题:one, two, .

我正在编写一个集合,其中的元素(键值对)与一些簿记信息一起存储:

struct Element {
    Key key;
    Value value;
    int flags;
};

std::vector<Element> elements;

(为简单起见,假设 KeyValue 都是标准布局类型。该集合无论如何都不会与任何其他类型一起使用。)

为了支持基于迭代器的访问,我编写了覆盖 operator->operator* 到 return 的迭代器,分别向用户提供指针和引用键值对。但是,由于集合的性质,永远不允许用户更改 returned 密钥。为此,我声明了一个 KeyValuePair 结构:

struct KeyValuePair {
    const Key key;
    Value value;
};

我已经在迭代器上实现了 operator->,如下所示:

struct iterator {
    size_t index;

    KeyValuePair *operator->() {
        return reinterpret_cast<KeyValuePair *>(&elements[index]);
    }
};

我的问题是:reinterpret_cast 的这种用法是定义明确的,还是调用了未定义的行为?我试图解释标准的相关部分并检查了有关类似问题的问题的答案,但是,我未能从中得出明确的结论,因为……:

仅使用这些信息,我发现无法推断 ElementKeyValuePair 结构是否共享一个共同的初始序列,或者是否有任何其他共同点可以证明我的 reinterpret_cast.

顺便说一句,如果您认为为此目的使用 reinterpret_cast 是不合适的,而且我确实面临 XY 问题,因此我应该简单地做一些其他事情来实现我的目标,请告诉我。

My question is: is this use of reinterpret_cast well-defined, or does it invoke undefined behavior?

reinterpret_cast 在这里是错误的方法,你只是违反了严格的别名。 reinterpret_castunion在这里出现分歧有点令人费解,但是这种情况的措辞非常清楚。

这样简单地定义联合可能会更好:

union elem_t {
   Element e{}; KeyValuePair p;
   /* special member functions defined if necessary */
};

... 并将其用作矢量元素类型。请注意,在确定布局兼容性时忽略 cv 限定 - [basic.types]/11:

Two types cv1 T1 and cv2 T2 are layout-compatible types if T1 and T2 are the same type, […]

因此 ElementKeyValuePair 确实共享一个共同的初始序列,并且访问 p 的相应成员,前提是 e 是活动的,是明确定义的.


另一种方法:定义

struct KeyValuePair {
    Key key;
    mutable Value value;
};

struct Element : KeyValuePair {
    int flags;
};

现在提供一个迭代器,它简单地包装向量中的 const_iterator 并向上转换要公开的 references/pointers。 key 不可修改,但 value 可以。