下面是我的场景:
有一组Instance
对象,在运行时确定对象的数量。
对于其中的每一个实例,都会创建一个自定义堆。(是的,我指的是::HeapCreate()
et。(所有win32函数)。
struct Instance
{
HANDLE heap;
};
现在,有一些特定于Instance
的状态对象,它可以访问(指针)实例。这是1:1的关系。每个州1次。
struct State
{
Instance * inst;
};
在这种状态下,我希望使用像std::vector
这样的STL容器,但是我希望这些容器使用一个分配器,它使用实例创建的堆。
阅读std::allocator
的历史,从C++98到C++17和更新,一些旧的需求已经被删除了,但是我要说的是,不可能为我上面所示的用例编写这样的分配器。考虑到分配器每次都是相同类型的,但是有状态的(在使用不同堆HANDLE
的情况下)。
因此,我的问题是:
std::pmr
C++17名称空间,并想知道其中是否有我还不熟悉的东西,这将帮助我处理我的用例。如果您展示了如何在现代(c++17和更新的) C++中解决这个问题的“惯用”方法,您的答案将是非常有价值的。
在这里,我的不完整和当前的“正在进行的工作”。随着时间的推移,我会根据答案和评论以及我自己的进步来填写更多的内容。
#include <Windows.h>
struct custom_heap_allocator
{
HANDLE heap;
// No default constructor
custom_heap_allocator() = delete;
// an instance is tied to a heap handle.
explicit custom_heap_allocator(HANDLE h)
: heap{ h }
{
}
// can I get away with this....
// copy constructor for same type.
custom_heap_allocator(const custom_heap_allocator& other)
: heap{ other.heap }
{
}
//... or do I need something like this? Or is it somehow covered by rebind?
//template<class U>
//custom_heap_allocator(const custom_heap_allocator<U>& other)
// : heap{ other.heap }
//{
//}
template<class U>
struct rebind {
typedef custom_heap_allocator other;
};
};
template <class T, class U>
constexpr bool operator== (const custom_heap_allocator& a1, const custom_heap_allocator& a2) noexcept
{
return a1.heap == a2.heap;
}
template <class T, class U>
constexpr bool operator!= (const custom_heap_allocator& a1, const custom_heap_allocator& a2) noexcept
{
return a1.heap != a2.heap;
}
备注:关闭Instance
只会破坏堆(不需要调用析构函数来获取堆上的东西,因为它们只是简单的数据,而不是系统资源等等。它们所持有的所有动态内容也来自同一个堆实例)。
发布于 2019-12-23 22:58:08
以下是您(编辑)问题中分配器的一个更完整的版本。
在Cpp.sh/4 4viaj上使用std::vector和std::list的一些基本单元测试
template<typename T>
struct custom_heap_allocator
{
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
// No default constructor
custom_heap_allocator() = delete;
// An instance is tied to a heap handle.
explicit custom_heap_allocator(HANDLE h)
: heap{ h }
{
}
// Instances are copy-constructable and copy-assignable.
custom_heap_allocator(const custom_heap_allocator&) = default;
custom_heap_allocator& operator=(const custom_heap_allocator&) = default;
// All related allocators share the same heap, regardless of type.
template<class U>
custom_heap_allocator(const custom_heap_allocator<U>& other)
: heap{ other.heap }
{
}
// Allocate and deallocate space for objects using the heap.
T* allocate(size_t n) {
return static_cast<T*>(HeapAlloc(heap, 0, sizeof(T) * n));
}
void deallocate(T* ptr, size_t n) {
HeapFree(heap, 0, ptr);
}
// Construct and destroy objects in previously allocated space.
// This *should* be optional and provided by std::allocator_traits,
// but it looks like some std containers don't use the traits.
template< class U, class... Args >
void construct( U* p, Args&&... args ) {
::new((void *)p) U(std::forward<Args>(args)...);
}
template< class U >
void destroy( U* p ) {
p->~U();
}
// Template for related allocators of different types.
template<class U>
struct rebind {
typedef custom_heap_allocator<U> other;
};
private:
// Heap used for all allocations/deallocations.
HANDLE heap;
// Allow all related types to access our private heap.
template<typename> friend struct custom_heap_allocator;
};
https://stackoverflow.com/questions/59464077
复制相似问题