c++ - 静态断言基指针 "equals"是派生指针

标签 c++ inheritance static-assert

假设我有一个具有共同基础的多态类层次结构:

struct Base { ~virtual Base() = default; };

我继承了一个大型代码库,其中包含一长串访问器函数(每个派生类型一个),这些函数通过 reinterpret_cast 获取派生指针:

Derived * Get()       // Derived inherits from Base
{
    Base * b = lookup_derived();
    return reinterpret_cast<Derived *>(b);
}

显然,代码应该使用static_castdynamic_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/

相关文章:

c++ - 这两行指针如何执行?

c++ - 为什么 operator = 返回 *this?

c++ - STD 错误 : wrong number of template arguments (1, 应该是 3)

swift - 将 UIGestureRecorgniser 的委托(delegate)设置为父级

c++ - 如何使用 std::is_volatile?

c++ - 使用 std::vector 和类对象时出错

c++ - 派生类 C++

java - 装饰器模式,子类通过其他子类运行以获得行为?

c++ - decltype(constexpr 变量)

c++ - 编译时检查和运行时检查 'at the same time'