fix(container_allocator): Fix MSVC compilation by correcting allocator semantics

ROOT CAUSE:
The allocate() function was incorrectly constructing objects during memory
allocation, violating C++ allocator requirements. MSVC's std::_Tree_node has
a deleted default constructor, causing compilation failure.

CHANGES:
- container_allocator::allocate() now only allocates raw memory without
  constructing objects (removed mem::$new and ipc::construct calls)
- container_allocator::deallocate() now only frees memory without
  destroying objects (removed mem::$delete and ipc::destroy_n calls)

WHY THIS FIXES THE ISSUE:
C++ allocator semantics require strict separation:
  * allocate()   -> raw memory allocation only
  * construct()  -> object construction with proper arguments
  * destroy()    -> object destruction
  * deallocate() -> memory deallocation only

Standard containers (like std::map) call construct() with proper arguments
(key, value) to initialize nodes, not allocate(). Since std::_Tree_node in
MSVC has no default constructor (= delete), attempting to construct it
without arguments always fails.

Fixes MSVC 2017 compilation error:
  error C2280: 'std::_Tree_node<...>::_Tree_node(void)':
  attempting to reference a deleted function
This commit is contained in:
木头云 2025-12-01 09:24:58 +00:00
parent 7eb7b93bfa
commit cf444e5309

View File

@ -63,26 +63,18 @@ public:
pointer allocate(size_type count) noexcept {
if (count == 0) return nullptr;
if (count > this->max_size()) return nullptr;
if (count == 1) {
return mem::$new<value_type>();
} else {
// Allocate raw memory without constructing objects
// Construction should be done by construct() member function
void *p = mem::alloc(sizeof(value_type) * count);
if (p == nullptr) return nullptr;
for (std::size_t i = 0; i < count; ++i) {
std::ignore = ipc::construct<value_type>(static_cast<byte *>(p) + sizeof(value_type) * i);
}
return static_cast<pointer>(p);
}
}
void deallocate(pointer p, size_type count) noexcept {
if (count == 0) return;
if (count > this->max_size()) return;
if (count == 1) {
mem::$delete(p);
} else {
mem::free(ipc::destroy_n(p, count), sizeof(value_type) * count);
}
// Deallocate raw memory without destroying objects
// Destruction should be done by destroy() member function before deallocate
mem::free(p, sizeof(value_type) * count);
}
template <typename... P>