我正在向系统中添加自定义内存分配器,并试图通过Allocator
概念正确地做到这一点,但是当到达所分配组件的类型时,我遇到了一些不确定性已被删除。
class Pimpl_interface {
public:
virtual ~Pimpl_interface() {}
virtual void foo() = 0;
};
template<typename T>
class Pimpl : public Pimpl_interface {
public:
void foo() override {}
};
template<typename Alloc = std::allocator<void>>
class MyType : public Alloc {
Pimpl_interface * pimpl_ = nullptr;
public:
MyType(const Alloc& alloc) : Alloc(alloc) {}
~MyType() {
if(pimpl_) {
pimpl_->~Pimpl_interface();
// What do I put here ?????
}
}
template<typename T>
void bar() {
using real_alloc_t = typename Alloc::template rebind<Pimpl<T>>::other;
real_alloc_t alloc(*static_cast<Alloc*>(this));
Pimpl<T>* ptr = alloc.allocate(1);
try {
pimpl_ = new(&ptr) Pimpl<T>();
}
catch(...) {
alloc.deallocate(ptr, 1);
throw;
}
}
};
乍一看,似乎要做的事情是将Alloc
重新绑定到Pimpl_interface
,并希望这样做是对的。我知道这可以与std::allocator
一起正常工作,但是用户分配器应该支持所有可重新分配的分配器类型吗?
在最坏的情况下,我可以使用类似鸭子类型的malloc/free
分配器对象,但如果可以的话,我宁愿尝试并遵循标准库。
答案 0 :(得分:0)
我觉得有很多事情要做。看起来似乎是事情的核心,您想要安全地使用替代分配器(尤其是在PImpl'd类中)。对我而言,该要求中最小的有用部分是使分配器与std::unique_ptr
一起使用。如果我正确遵循,我想您会希望它是std::unique_ptr<T, std::function<void(T*)>>
。
同样,看起来std::allocate_shared
可能与您想要的足够接近。 https://en.cppreference.com/w/cpp/memory/shared_ptr/allocate_shared
这是您需要的吗?:
template<typename Alloc = std::allocator<void>>
class MyType {
Alloc alloc_;
std::shared_ptr<Pimpl_interface> pimpl_ = nullptr;
public:
MyType(const Alloc& alloc) : Alloc(alloc) {}
~MyType() {} // shared_ptr ftw.
template<typename T>
void bar() {
using real_alloc_t = typename Alloc::template rebind<Pimpl<T>>::other;
real_alloc_t alloc(alloc_);
pimpl_ = std::allocate_shared<Pimpl<T>>(alloc);
}
};
(我放弃了Alloc
的继承权,因为这看起来像个骰子。)