假设我有以下类型:
struct A {
int a;
};
struct B {
int b;
};
struct C : public A, public B {
int c;
};
A C*
指针可以转换为A*
指针根本不调整实际地址。但当C*
被投射到B*
,该值必须改变。我想确保我拥有的两个相关类型可以在不更改地址的情况下相互转换(即没有多重继承,或者基类是派生类的第一个基类)。这可以在运行时检查,例如像这样
assert(size_t(static_cast<A*>((C*)0xF000) == 0xF000);
assert(size_t(static_cast<B*>((C*)0xF000) != 0xF000);
这样可行。但这些信息在编译时是已知的,所以我正在寻找一种方法来对其进行编译时断言。将上述内容转换为静态断言的明显方法(例如替换assert
with BOOST_STATIC_ASSERT
使用 g++ 4.2 给出错误“对除整型或枚举类型之外的类型的强制转换不能出现在常量表达式中”。
便携性并不是太重要。使用 gcc 扩展或 hacky 模板技巧都可以。
Update:发现之前几乎有人问过同样的问题:C++,静态检测具有不同地址的基类? https://stackoverflow.com/questions/1131643/c-statically-detect-base-classes-with-differing-addresses. Using offsetof()
也是唯一有用的建议。
“我想确保两个相关类型可以在不更改地址的情况下相互转换(即没有多重继承,或者基类是派生类的第一个基类)。”
你的“即”不正确。例如,前 4 个字节完全有可能是Derived
是一个 vtable 指针,即使当Base
不是多态的。是的,如果 (1) 第一个基子对象位于偏移量 0 处,并且 (2) vtable 指针位于偏移量 0 处,C++ 编译器会更容易。但这两个目标本质上是不一致的,并且没有明显更好的选择。
现在,第一部分可以在理论上进行测试。对于标准布局类型,不会有什么区别offset_of(Base, first_member)
and offset_of(Derived, first_member)
。但在实践中,offset_of
不适用于有趣的类型;是UB。此检查的重点是检查类型,因此对于非标准布局类型,它应该可靠地失败。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)