【发布时间】:2016-01-23 13:51:32
【问题描述】:
我查看了以下相关的问题,但似乎都没有解决我的确切问题:one、two、three。
我正在编写一个集合,其中存储了元素(键值对)以及一些簿记信息:
struct Element {
Key key;
Value value;
int flags;
};
std::vector<Element> elements;
(为简单起见,假设Key 和Value 都是标准布局类型。无论如何,该集合不会与任何其他类型一起使用。)
为了支持基于迭代器的访问,我编写了覆盖operator-> 和operator* 的迭代器,分别向用户返回指向键值对的指针和引用。但是,由于集合的性质,永远不允许用户更改返回的密钥。为此,我声明了一个KeyValuePair 结构:
struct KeyValuePair {
const Key key;
Value value;
};
我已经在迭代器上实现了operator->,如下所示:
struct iterator {
size_t index;
KeyValuePair *operator->() {
return reinterpret_cast<KeyValuePair *>(&elements[index]);
}
};
我的问题是:reinterpret_cast 的这种使用是明确定义的,还是会调用未定义的行为?我试图解释标准的相关部分并检查了有关类似问题的问题的答案,但是,我未能从中得出明确的结论,因为……:
- 这两种结构类型共享一些初始数据成员(即
key和value),它们的区别仅在于const-qualification; - 标准没有明确说明
T和cv T是布局兼容的,但也没有说明相反的情况;此外,它还要求它们具有相同的代表性和一致性要求; - 如果第一个但许多成员具有布局兼容类型,则两个标准布局类类型共享一个共同的初始序列;
- 对于包含共享公共初始序列的类类型成员的联合类型,允许使用任一联合成员 (9.2p18) 检查此类初始序列的成员。
– 没有类似的明确保证
reinterpret_casted 指向结构的指针共享一个共同的初始序列。 – 但是,可以保证指向结构的指针指向其初始成员 (9.2p19)。
仅使用这些信息,我发现无法推断出 Element 和 KeyValuePair 结构是否共享一个共同的初始序列,或者有任何其他共同点可以证明我的 reinterpret_cast 是合理的。
顺便说一句,如果您认为将reinterpret_cast 用于此目的是不合适的,并且我确实面临 XY 问题,因此我应该简单地做些其他事情来实现我的目标,请告诉我。
【问题讨论】:
-
您要求language-lawyer 判断吗?它真的有效吗?
reinterpret_cast几乎总是错误的方法,const_cast不应该很好地满足您的要求吗? -
@πάνταῥεῖ 是的,我正在请求语言律师的判断。 我无法判断它是否真的有效 或者它只是“似乎有效”,因为我不知道它是否会调用未定义的行为。我不知道
const_cast是否应该在这种情况下工作,但让我试一试——目前还不清楚const_cast编译是否意味着这是明确定义的。 -
“但是,无论const_cast编译是否意味着这是定义明确的。” 当然,我认为这就是它的目的。使用
reinterpret_cast不能保证任何事情。
标签: c++ c++11 language-lawyer reinterpret-cast strict-aliasing