c – 如何进行静态断言,指针转换是微不足道的?

前端之家收集整理的这篇文章主要介绍了c – 如何进行静态断言,指针转换是微不足道的?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
假设我有这些类型:
struct A {
    int a;
};

struct B {
    int b;
};

struct C : public A,public B {
    int c;
};

可以将C *指针强制转换为A *指针,而根本不调整实际地址.但是当C *被转换为B *时,该值必须改变.我想确保我所拥有的两个相关类型可以在不改变地址的情况下相互转换(即没有多重继承,或者基类是派生类的第一个基础).这可以在运行时检查,例如像这样

assert(size_t(static_cast<A*>((C*)0xF000) == 0xF000);
assert(size_t(static_cast<B*>((C*)0xF000) != 0xF000);

这样可行.但是这个信息在编译时是已知的,所以我正在寻找一种方法来对它进行编译时断言.将上述转换为静态断言的明显方法(例如,用BOOST_STATIC_ASSERT替换断言)将错误“强制转换为除积分或枚举类型之外的类型”不能出现在带有g 4.2的常量表达式中.

便携性不是很重要.使用gcc扩展或hacky模板技巧都可以.

更新:发现之前已经问过几乎相同的问题:C++,statically detect base classes with differing addresses?.使用offsetof()也是唯一有用的建议.

解决方法

“我想确保两个相关类型可以相互转换而不需要更改地址(即没有多重继承,或者基类是派生类的第一个基础).”

你的“ie”是不对的.例如,Derived的前4个字节完全有可能是vtable指针,即使Base不是多态的.是的,如果(1)第一个基础子对象位于偏移0处,并且(2)vtable指针位于偏移0处,则C编译器更容易.但是这两个目标本质上是不一致的,并且没有明显更好的选择.

现在,第一部分可以在理论上进行测试.对于标准布局类型,offset_of(Base,first_member)和offset_of(Derived,first_member)没有区别.但实际上,offset_of对于有趣的类型不起作用;这是UB.此检查的重点是检查类型,因此对于非标准布局类型,它应该可靠地失败.

原文链接:/c/118342.html

猜你在找的C&C++相关文章