在 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; };
在 Type
和 Wrapper<Type>
之间 reinterpret_cast
对于什么类型是安全的? None?标准布局?全部?
假设我们创建了其中一个对象(Type
和Wrapper<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
示例)
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。
假设我们有这样的 class 模板 Wrapper
:
template <class T>
struct Wrapper { T wrapped; };
在 Type
和 Wrapper<Type>
之间 reinterpret_cast
对于什么类型是安全的? None?标准布局?全部?
假设我们创建了其中一个对象(Type
和Wrapper<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";
}
阅读
因为我很确定,这些转换确实有效。
将 T
(不是 Wrapper<T>
的成员)重新解释为 Wrapper<T>
是绝对不允许的(F1
示例)。
另一方面,我认为将 Wrapper<T>
重新解释为 T
对于标准布局 类 是允许的:(F2
示例)
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。