在 Type 和 Wrapper<Type> 之间 reinterpret_cast 安全吗?

Is it safe to reinterpret_cast between a Type and a Wrapper<Type>?

假设我们有这样的 class 模板 Wrapper

template <class T>
struct Wrapper { T wrapped; };

TypeWrapper<Type> 之间 reinterpret_cast 对于什么类型是安全的? None?标准布局?全部?

假设我们创建了其中一个对象(TypeWrapper<Type>),并通过另一个对象读写这个对象。示例 (live on godbolt.org):

void F1() {
    std::stringstream ss;
    ss << "Hello";
    reinterpret_cast<Wrapper<std::stringstream>&>(ss).wrapped << " world";
}

void F2() {
    Wrapper<std::stringstream> ss;
    ss.wrapped << "Hello";
    reinterpret_cast<std::stringstream&>(ss) << " world";
}

阅读 的评论,这方面似乎在标准中不是很明确。我认为所有编译器都会生成按预期工作的代码(即一种类型的值可以转换为另一种类型),但标准目前可能无法保证这一点。如果没有,就会出现问题:标准能否保证这些转换的明确定义的行为,或者在这种情况下是否possible/impractical 不能保证任何事情?

因为我很确定,这些转换确实有效。

T(不是 Wrapper<T> 的成员)重新解释为 Wrapper<T> 是绝对不允许的(F1 示例)。

另一方面,我认为将 Wrapper<T> 重新解释为 T 对于标准布局 类 是允许的:(F2 示例)

[basic.compound]/4.3

Two objects a and b are pointer-interconvertible if:

— one is a standard-layout class object and the other is the first non-static data member of that object, or ...

在其正下方:

If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_­cast. ...

请注意,虽然此规则是对称的,但它要求两个对象都实际存在。如果您有指向 Wrapper<T> 成员的 T 的引用,那么您可以将其重新解释为 Wrapper<T>(反之亦然)。但是如果它指向一个不是 Wrapper<T> 成员的 T 对象,那么它将是 UB。


免责声明:“不允许这样那样的重新解释”是指访问 reinterpret_cast 的结果会导致 UB。演员表本身不应导致 UB。