I'm writing a fixed size allocator. I'm curious what I'm doing is UB.
#include <type_traits>
#include <stdexcept>
template <typename T>
concept DiskAllocable = std::is_same_v<std::remove_cvref_t<T>, T>
&& std::is_trivially_copyable_v<T> && (sizeof(T) % alignof(T) == 0);
template <DiskAllocable T, size_t Count = 1> class AllocatorFixed {
static_assert(Count > 0, "count should be nonzero");
static constexpr size_t block_size_ = (sizeof(T) * Count);
static_assert(block_size_ >= sizeof(T *),
"block size should be at least pointer size");
union Chunk {
T *next_;
T object_[Count];
};
T *pool_ = nullptr;
size_t pool_size_ = 0;
Chunk *free_ = nullptr;
public:
using value_type = T;
AllocatorFixed(unsigned char *pool_ptr, size_t pool_byte_size) {
if (!pool_ptr) {
throw std::invalid_argument("pool ptr is null");
}
if (pool_byte_size < block_size_) {
throw std::invalid_argument("pool byte size is too small");
}
pool_ = reinterpret_cast<T *>(pool_ptr);
pool_size_ = pool_byte_size / block_size_;
T* chunk_ptr = pool_;
for (size_t i = 0; i < pool_size_; i++, chunk_ptr += Count) {
auto chunk = reinterpret_cast<Chunk *>(chunk_ptr);
chunk->next_ = chunk_ptr + Count;
}
free_ = reinterpret_cast<Chunk *>(pool_);
}
// ... other details ...
};
I'm using Chunk
as a union of actual chunk block and T*
, and I'm writing all Chunk.next_
as the pointer value to the next Chunk
. I'm worried if this is UB.