[英]C++: Can't propagate polymorphic_allocator with scoped_allocator_adaptor
[英]How can I use scoped_allocator_adaptor with a custom allocator (wrapped in a class) so that it can be unwrapped for some types but not STL containers?
我不知道如何更好地表達我的問題。
我對std::scoped_allocator_adaptor
理解是它將分配器實例傳遞給容器,並使用它來構造通過emplace_back
在容器中構造的元素/容器,如果它們需要這樣的分配器參數)。
我有以下內容,它有點冗長,但這是我能做到的最低限度,說明我正在嘗試做的事情:
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <vector>
#include <scoped_allocator>
#include <concepts>
namespace custom_memory
{
class CustomAllocator
{
public:
CustomAllocator(const std::size_t sizeBytes,
void* const start)
:
m_sizeBytes(sizeBytes),
m_usedBytes(0),
m_start(start),
m_current(start)
{
}
void* Allocate(const std::size_t& numBytes,
const std::uintptr_t& alignment)
{
std::size_t space = m_sizeBytes - m_usedBytes;
if(std::align(alignment, numBytes, m_current, space))
{
// the amount used for alignment
m_usedBytes += (m_sizeBytes-m_usedBytes) - space;
// the amount actually needed
m_usedBytes += numBytes;
void* address = m_current;
m_current = reinterpret_cast<void*>(
reinterpret_cast<std::uintptr_t>(m_current) + numBytes);
return address;
}
throw std::bad_alloc();
}
void Free(void* const ptr)
{
// do nothing in this Allocator, but other derived types may
}
void Clear()
{
m_current = m_start;
m_usedBytes = 0;
}
std::size_t GetSize() const { return m_sizeBytes; }
protected:
const std::size_t m_sizeBytes;
std::size_t m_usedBytes;
void* const m_start;
void* m_current;
};
// many types derive from base CustomAllocator type
// allows for my custom allocators to be used in STL containers
template<typename T, typename Alloc>
class STLAdaptor
{
public:
typedef T value_type;
STLAdaptor(Alloc* allocator)
:
m_allocator(allocator)
{
}
[[nodiscard]] constexpr T* allocate(std::size_t n)
{
return reinterpret_cast<T*>
(m_allocator->Allocate(n * sizeof(T), alignof(T)));
}
constexpr void deallocate(T* p, std::size_t n)
{
m_allocator->Free(p);
}
std::size_t MaxAllocationSize() const
{
return m_allocator->GetSize();
}
protected:
Alloc* m_allocator;
};
template<typename T, typename Allocator>
using vector = std::vector<T,
std::scoped_allocator_adaptor<STLAdaptor<T, Allocator>>>;
}
// overloads of global new and delete so I can use them with
// my custom allocators
void* operator new(std::size_t size, custom_memory::CustomAllocator& allocator,
std::uintptr_t alignment)
{
return allocator.Allocate(size, alignment);
}
void operator delete(void* ptr, custom_memory::CustomAllocator& allocator)
{
allocator.Free(ptr);
}
// a type that needs an allocator for it's own internal use
template<typename A>
requires std::derived_from<A, custom_memory::CustomAllocator>
struct Foo
{
A* m_allocator;
int* m_foos;
Foo(A* a)
:
m_allocator(a),
m_foos(new (*a, alignof(int)) int(7))
{
}
Foo(const Foo<A>& other)
:
m_allocator(other.m_allocator),
m_foos(new (*m_allocator, alignof(int)) int(*(other.m_foos)))
{
}
~Foo()
{
operator delete (m_foos, *m_allocator);
}
Foo<A>& operator=(const Foo<A>& rhs)
{
m_allocator = rhs.m_allocator;
*m_foos = *(rhs.m_foos);
return *this;
}
};
int main()
{
const std::size_t memSize = 10000000;
void* mem = std::malloc(memSize);
typedef Foo<custom_memory::CustomAllocator> FooType;
custom_memory::CustomAllocator customAlloc(memSize, mem);
// this works
{
std::vector<FooType, custom_memory::STLAdaptor<FooType,
custom_memory::CustomAllocator>>
vec(&customAlloc);
vec.emplace_back(&customAlloc);
}
// this works
{
custom_memory::vector<FooType,custom_memory::CustomAllocator>
vec(&customAlloc);
vec.emplace_back(&customAlloc); // <-- I don't want to pass this
}
// this doesn't work
{
custom_memory::vector<FooType,custom_memory::CustomAllocator>
vec(&customAlloc);
vec.emplace_back(); // <--- I thought scoped_allocator_adaptor
// would pass the allocator to constructed
// elements?
}
// this also doesn't work
{
typedef std::basic_string<char, std::char_traits<char>,
custom_memory::STLAdaptor<char, custom_memory::CustomAllocator>>
StringType;
custom_memory::vector<StringType,custom_memory::CustomAllocator>
vec(&customAlloc);
vec.emplace_back("string");
}
std::free(mem);
return 0;
}
我有一個從基(未顯示)派生的CustomAllocator
並且有一堆從這個基派生的不同分配器。
我有一個STLAdaptor
,它允許在 STL 容器中使用CustomAllocator
。 這是一個模板化類,因為上面提到了許多不同的分配器(我實際上也有針對不同分配器的STLAdaptor
,未顯示)。
我嘗試對std::vector
進行typedef
,它在std::scoped_allocator_adaptor
使用我的STLAdaptor
包裝的CustomAllocator
。
然后我重載全局new
和delete
以接受CustomAllocator
進行分配。
最后,我有一個需要CustomAllocator
的類,它在內部使用它為內部類型分配內存(這是我的用例)。
你可以在我的測試中看到我可以:
制作一個成功使用我的STLAdaptor
包裝的CustomAllocator
的std::vector
。 我可以用Foo<CustomerAllocator>
類型填充它。
我可以使用std::scoped_allocator_adaptor
std::vector
typedef。 但我需要將CustomAllocator
實例顯式傳遞給內部類型
我不能省略,但我想
我也想使用其他 STL 容器
我很確定問題在於std::scoped_allocator_adaptor
有一個STLAdaptor
分配器,而不是CustomAllocator
。 但是我也不能讓它與std::string
一起工作,但我認為這與STLAdaptor
在std::vector
和std::string
之間具有不同類型有關(這是rebind
進入的地方玩?
我正在使用 GCC 10.2.0 和 C++20
任何幫助,將不勝感激。
我很確定問題在於
std::scoped_allocator_adaptor
有一個STLAdaptor
分配器,而不是CustomAllocator
。
就目前而言,這是正確的。 scoped_allocator_adaptor
將傳遞它所擁有的東西,而不是它不知道的其他類型。
此外, scoped_allocator_adaptor
將使用uses_allocator
來確定類型是否使用分配器。 該特征默認查看該類型是否定義了分配器可以轉換為的成員類型allocator_type
。
但是我也不能讓它與
std::string
一起工作,但我認為這與STLAdaptor
在std::vector
和std::string
之間具有不同類型有關(這是rebind
進入的地方玩?
正確的。 STLAdaptor
不符合分配器要求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.