English 中文(简体)
如何在汇编时间核实重新翻译的有效性
原标题:How to verify the validity of reinterpret_cast at compile time
  • 时间:2011-11-03 10:11:27
  •  标签:
  • c++

在汇编时间期间,一个点子(无论是衍生的还是基的)上台/下台不会改变点值。 这就是说,该插文相当于<代码>reinterpret_cast。

具体设想如下: 我有一个<代码>Base 类别和Derived(明显取自Base)。 还有一个模板:<代码>Wrapper类别,由指定为模板参数的那类点人组成。

class Base
{
    // ...
};

class Derived
    :public Base
{
    // ...
};

template <class T>
class Wrapper
{
    T* m_pObj;
    // ...
};

在某些情形下,我有不同的类型:<代码>Wrapper<Derived>,而我也希望称一种功能,即获得(最先进的)参考资料-ro <代码>Wrapper<Base>。 显然,这里没有自动投放,Wrapper<Derived>不是来自Wrapper<Base>

void SomeFunc(const Wrapper<Base>&);

Wrapper<Derived> myWrapper;
// ...

SomeFunc(myWrapper); // compilation error here

在标准C++范围内有处理这种情况的办法。 与此类似:

Derived* pDerived = myWrapper.Detach();

Wrapper<Base> myBaseWrapper;
myBaseWrapper.Attach(pDerived);

SomeFunc(myBaseWrapper);

myBaseWrapper.Detach();
myWrapper.Attach(pDerived);

但我不喜欢这样做。 这不仅需要一个宽松的子,而且还会产生额外的代码,因为Wrapper有一个非游子(如你可能猜测),而Im则使用例外处理。 OTOH 如果Base Derived相同(例如,由于没有多重继承),只能将myWrapper投到所需的类型和SomeFunc,并且将发挥作用!

因此,在<代码>Wrapper上添加如下内容:

template <class T>
class Wrapper
{
    T* m_pObj;
    // ...

    typedef T WrappedType;


    template <class TT>
    TT& DownCast()
    {
        const TT::WrappedType* p = m_pObj; // Ensures GuardType indeed inherits from TT::WrappedType

        // The following will crash/fail if the cast between the types is not equivalent to reinterpret_cast
        ASSERT(PBYTE((WrappedType*)(1)) == PBYTE((TT::WrappedType*)(WrappedType*)(1)));

        return (TT&) *this; // brute-force case
    }

    template <class TT> operator const Wrapper<TT>& () const
    {
        return DownCast<Wrapper<TT> >();
    }
};


Wrapper<Derived> myWrapper;
// ...

// Now the following compiles and works:
SomeFunc(myWrapper);

问题在于,在某些情况下,军force不成立。 例如:

class Base
{
    // ...
};

class Derived
    :public AnotherBase
    ,public Base
{
    // ...
};

在此,点人对<代码>Base的价值与<代码>的出入。 因此,Wrapper<Derived>并不等于Wrapper<Base>

我愿发现和防止这种无效播种的企图。 我添加了核查(如你可能看到的那样),但它在run-time进行。 也就是说,该法典将汇编和操作,在运行期间,在 de楼发生坠毁(或失败的断言)。

这是罚款,但是,我很想在汇编时间时赶上这笔钱,而没有建筑。 统计局。

是否有办法实现这一目标?

最佳回答

简短回答:no

长期回答:

汇编时可用的预测有限,例如,如果B类是另一个D类可进入的基类,则你可以发现(使用功能超负荷分辨率)。

然而,这种情况却令人不安。

《标准》并不要求全局检查,特别是:

  • you cannot list the (direct) base classes of a class
  • you cannot know whether a class has only one or several base classes
  • you cannot even know if a base class is the first base or not

And of course, there is the issue that the object layout is more or less unspecified, anyway (though C++11 adds the ability to distinguish between trivial layout and class with virtual methods if I remember correctly, which helps a bit here!)

Using Clang, and its AST inspection capabilities, I think you could write a dedicated checker, but this seems quite complicated, and is of course totally non-portable.

Therefore, despite your bold claim P.S. Please don t reply with "why do you want to do this" or "this is against the standard". I know what what all this for, and I have my reasons to do this., you will have to adapt your ways.

当然,如果更广泛地了解你对这一阶层的利用情况,我们或许能够把我们的大脑聚集在一起,帮助你们找到更好的解决办法。


How to implement a similar system ?

首先,我要提出一个简单的解决办法:

  • Wrapper<T> is the owner class, non-copyable, non-convertible
  • WrapperRef<U> implements a proxy over an existing Wrapper<T> (as long as T* is convertible to U*) and provide the conversions facilities.

We will use the fact that all pointers to be manipulated inherit from UnkDisposable (this is a crucial information!)

法典:

namespace details {
  struct WrapperDeleter {
    void operator()(UnkDisposable* u) { if (u) { u->Release(); } }
  };


  typedef std::unique_ptr<UnkDisposable, WrapperDeleter> WrapperImpl;
}

template <typename T>
class Wrapper {
public:
  Wrapper(): _data() {}

  Wrapper(T* t): _data(t) {}

  Wrapper(Wrapper&& right): _data() {
    using std::swap;
    swap(_data, right._data);
  }

  Wrapper& operator=(Wrapper&& right) {
    using std::swap;
    swap(_data, right._data);
    return *this;
  }

  T* Get() const { return static_cast<T*>(_data.get()); }

  void Attach(T* t) { _data.reset(t); }
  void Detach() { _data.release(); }

private:
  WrapperImpl _data;
}; // class Wrapper<T>

既然我们奠定了基础,我们就能够作出适应性的代理。 由于我们将只通过<代码>WrapperImpl对一切进行操纵,我们通过在模板中核对转换成<代码>:enable_if和:is_base_of,确保了类型安全(以及我们的<代码>的有意义性:

template <typename T>
class WrapperRef {
public:
  template <typename U>
  WrapperRef(Wrapper<U>& w,
    std::enable_if_c< std::is_base_of<T, U> >::value* = 0):
    _ref(w._data) {}

  // Regular
  WrapperRef(WrapperRef&& right): _ref(right._ref) {}
  WrapperRef(WrapperRef const& right): _ref(right._ref) {}

  WrapperRef& operator=(WrapperRef right) {
    using std::swap;
    swap(_ref, right._ref);
    return *this;
  }

  // template
  template <typename U>
  WrapperRef(WrapperRef<U>&& right,
    std::enable_if_c< std::is_base_of<T, U> >::value* = 0):
    _ref(right._ref) {}

  template <typename U>
  WrapperRef(WrapperRef<U> const& right,
    std::enable_if_c< std::is_base_of<T, U> >::value* = 0):
    _ref(right._ref) {}

  T* Get() const { return static_cast<T*>(_ref.get()); }

  void Detach() { _ref.release(); }

private:
  WrapperImpl& _ref;
}; // class WrapperRef<T>

可能根据您的需要加以压缩,例如,你可以取消复制和复制<代码>WrapperRef类别的能力,以避免出现已失效的<代码>Wrapper的情况。

另一方面,你也可以利用<条码>共享_ptr/<条码>/<>wak_ptr来充实这一条。 能够复制和移动包装,并且仍然能够保证(但了解记忆泄漏)。

<>说明:有意<代码>WrapperRef不提供 每一“<>/代码”方法,不能使用基类。 否则,请在<代码>Fruit 上填写Banana,通过<代码>WrapperRef<Fruit>,即使原始代码是<编码>Wrapper<Apple>。

Note: this is easy because of the common UnkDisposable base class! This is what gives us a common denominator (WrapperImpl).

问题回答

暂无回答




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签