所以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)
这会表现出某些多态类型的未定义行为吗?
如果你使用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> };
}
Run Code Online (Sandbox Code Playgroud)