假设我有一个具有共同基础的多态类层次结构:
struct Base { ~virtual Base() = default; };
我继承了一个大型代码库,其中包含一长串访问器函数(每个派生类型一个),这些函数通过 reinterpret_cast
获取派生指针:
Derived * Get() // Derived inherits from Base
{
Base * b = lookup_derived();
return reinterpret_cast<Derived *>(b);
}
显然,代码应该使用static_cast
或dynamic_cast
(取决于基础是否是虚拟的)。但是,由于这个翻译单元很大,并且所有派生类的定义都很大,因此 TU 不包含 Derived
的定义,而仅包含其声明。
我想通过向每个派生类定义添加一个静态断言来使此代码更加健壮,该静态断言表明此重新解释转换将产生正确的结果。本质上,我想要这样的东西:
struct Derived : Base
{
static_assert(static_cast<Derived *>(std::declval<Base *>()) ==
reinterpret_cast<Derived *>(std::declval<Base *>()));
// ...
};
这种构造当然不起作用,因为不得评估 declval
,并且重新解释转换的结果不是常量表达式。是否有任何标准的 C++ 机制可以静态执行此类测试? (另一种方法是在类构造函数中对 this
进行运行时检查。)
编辑:根据亚伦的帖子,我突然意识到这个问题可以完全不用reinterpret_casts来表达:
static_cast<void *>(std::declval<Derived *>()) ==
static_cast<void *>(static_cast<Base *>(std::declval<Derived *>()))
最佳答案
我不确定这是否足以满足您的设置,但是 this code on ideone对我有用(clang 3.5.0 和 g++ 4.9.3)。
更新为向另一个方向转换,即。 Derived*
-到- Base*
,更紧密地匹配问题。并且还更新为使用static_cast<void*>
显式地代替 C 风格转换和 reinterpret_cast
.
template<typename D, typename B>
struct CheckCasting {
static D d_static;
constexpr
static B* bp = &d_static; // the original object is D,
// that allows us to static_cast both ways
static
constexpr bool static_equals_reinterpret() {
return static_cast<void*>(static_cast<D*>(bp))
== static_cast<void*>( bp );
}
};
struct Base {
constexpr Base() : i(0) {}
int i;
};
struct derived_with_virtual : public Base {
derived_with_virtual() {}
virtual void foo() { }
};
struct without_virtual : public Base {
without_virtual() {}
};
static_assert( ! CheckCasting<derived_with_virtual, Base> :: static_equals_reinterpret() ,"");
static_assert( CheckCasting<without_virtual , Base> :: static_equals_reinterpret() ,"");
一些评论:
- 我尝试将类型转换替换为
void*
与reinterpret_cast,但clang不喜欢那样。 “注意:常量表达式中不允许reinterpret_cast”。 - 我尝试移动
static_assert
在派生类中没有成功。 - 这需要为每个派生类静态分配一个对象。
关于c++ - 静态断言基指针 "equals"是派生指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31878000/