C++编译时断言,BASE是基类的延伸,具有相同的内存地址
问题描述:
struct A
{
};
struct B : A
{
virtual ~B() {}
};
template<typename BASE, typename EXTENDED>
void ASSERT_BASE_EXTENDED()
{
static_assert(static_cast<BASE*>((EXTENDED*)256)==(BASE*)256, "error");
}
我正在寻找一种方式来有一个编译时断言检查,如果基类的延伸的基础,他们有相同的内存地址。C++编译时断言,BASE是基类的延伸,具有相同的内存地址
在上面的例子中,即使B是基于A的,当被转换为A时它具有不同的存储器地址,因为虚拟函数表指针实际上是B的第一个成员。但是我需要检查如果A是第一名成员。
上述工作正常,但不是编译时,因为我得到一个错误:使用VS 2017年编译器时,“错误C2131表达式的结果不是一个常量”。
我不感兴趣“的std :: is_base_of”,因为这一个忽略检查相同的内存地址。 有没有另一种方法来做到这一点?
谢谢
答
内存地址是一个运行时构造。你不能在编译时检查它们,因为那时它们不存在。你提到的那种铸造也是如此。完全在运行时发生。您必须使用运行时检查和错误处理来替换static_assert
,例如一个assert()
或一个例外。
这对国际海事组织共同使用的情况。对于你的例子中的硬编码内存地址,问题是这些地址插入指针。要做到这一点的唯一有效的办法就是reinterpret_cast的(这是编译器试图为C样式转换在你的榜样铸件中的一个),因为该类型INT和指针到T完全无关。但是reinterpret_cast在编译时是不允许的。
锵的错误消息所言很好:
main.cpp:14:38: note: cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression
static_assert(static_cast<BASE*>((EXTENDED*)256)==(BASE*)256, "error");
^
你想使用[_CRTP_(https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)和'static_cast'? – user0042
CRTP是一个有趣的概念,但目标是不要修改现有的类,只调整ASSERT_BASE_EXTENDED函数。 – Esenthel