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

Mat*_*son 3 c++ c++11

所以gcc 4.9.0实现一个static_assert离子该类型是不void被正确地符合标准.这很棒,一切都符合标准.

我有一个变体类型存储数据下std::unique_ptr<void>现在不起作用.简单的解决方法是将其更改为a 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;
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*ely 9

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

如果你使用unique_ptr<void, void(*)(void*)>(new X(...), Deleter<X>)它将是正确的X,因为删除器使用正确的动态类型的对象.

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

但是,你应该使用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> };
  }
Run Code Online (Sandbox Code Playgroud)