gcc 4.9.0 </void>不接受std :: unique_ptr <void>

时间:2014-05-06 12:02:13

标签: c++ c++11

因此gcc 4.9.0 implemented static_assertvoid离子类型不是std::unique_ptr<void>才能正确符合标准。这很棒,一切都符合标准。

我有一种变体类型,它将数据存储在std::shared_ptr<void>下,现在无效。简单的解决方法是将其更改为unique_ptr并立即编译。更好的解决方法是提供删除函数。

以下是修复#include <memory> #include <iostream> template<typename T> void Deleter(void * p) { delete reinterpret_cast<T*>(p); } int main() { const std::unique_ptr<void, void(*)(void*)> v(new int(199), Deleter<int>); std::cout << *reinterpret_cast<int*>(v.get()) << std::endl; return 0; } 的安全方法吗?这会出现某些多态类型的未定义行为吗?

{{1}}

1 个答案:

答案 0 :(得分:9)

  

这会出现某些多态类型的未定义行为吗?

如果您使用unique_ptr<void, void(*)(void*)>(new X(...), Deleter<X>)对任何X都是正确的,因为删除器使用对象的正确动态类型。

如果您使用unique_ptr<void, void(*)(void*)>(new Derived(...), Deleter<Base>)将会有未定义的行为(对于多态和非多态类型),如果Base没有虚拟析构函数,或者Base子对象与包含它的Derived对象的地址不同。

但是,您应该在两个地方使用static_cast而不是reinterpret_cast。您应该更喜欢使用最适合特定情况的强制转换,reinterpret_cast是一个大锤。

为了使代码不易出错,我会写一个辅助函数,所以你只需要输入一次类型,如:

template<typename T, typename... Args>
  std::unique_ptr<void, void(*)(void*)>
  make_unique_void_ptr(Args&&... args)
  {
    using Ptr = std::unique_ptr<void, void(*)(void*)>;
    return Ptr{ new T(std::forward<Args>(args)...), Deleter<T> };
  }