【发布时间】:2020-10-27 03:32:29
【问题描述】:
假设我们有这样的类模板Wrapper:
template <class T>
struct Wrapper { T wrapped; };
对于reinterpret_cast 在Type 和Wrapper<Type> 之间的哪些类型是安全的?没有?标准布局?全部?
假设我们创建了其中一个对象(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";
}
阅读this answer这个领域的cmets在标准上似乎不是很明确。我认为所有编译器都会生成按预期工作的代码(即一种类型的值可以转换为另一种类型),但标准目前可能无法保证这一点。如果没有,问题就出现了:标准能否保证这些强制转换的明确行为,或者在这种情况下保证任何东西是不可能/不切实际的?
因为我很确定,这些演员阵容确实有效。
【问题讨论】:
-
"阅读这个答案的 cmets 这个领域在标准中似乎不是很明确。" 阅读这些 cmets 只告诉我有些人不知道认为 C++ 应该 是那样的,而不是 C++ 实际上不是那样的。该评论线程中的许多人都以他们对此事的看法而闻名,这与 C++ 对象模型的实际工作方式不一致。
-
"标准能否保证这些强制转换的明确行为,或者在这种情况下保证任何东西是不可能/不切实际的?" 这个问题没有任何意义。标准“可以”保证任何事情。 C++ 标准通常不关注编译器认为“定义明确的行为”然后说“那是 C++”。标准定义什么是明确定义的,如果在特定情况下某些其他东西碰巧适用于特定实现,那与标准无关。
-
@NicolBolas:但是,如果某些未标准化的东西适用于所有编译器,并且具有实际意义,我认为它可能会被放入标准中。
-
这通常不是标准中某些内容的原因。尤其是当它涉及诸如 C++ 对象模型之类的基本概念时。它最终必须是有意义的,而你所说的至少有一半没有。
-
"我可以向你保证,这是有道理的" 不,它没有。如果那里没有
Wrapper<Type>对象,那么尝试访问它是没有意义的。你不能假装那里没有一个物体。为了使这有意义,您必须从根本上改变“对象”对 C++ 的意义的idea。您基本上是在说“对象”只是您目前看待一段记忆的方式,除此之外没有任何意义。
标签: c++ language-lawyer undefined-behavior reinterpret-cast strict-aliasing