Require types used with construct are trivially destructible

This commit is contained in:
2025-08-14 12:06:42 -04:00
parent ba827a71ce
commit 9d4c08747c
2 changed files with 49 additions and 19 deletions

View File

@@ -5,6 +5,7 @@
#include <cstdint>
#include <cstdlib>
#include <new>
#include <type_traits>
#include <utility>
/**
@@ -36,8 +37,9 @@
* ArenaAllocator arena(1024);
* void* ptr = arena.allocate(100);
*
* // Construct objects in-place
* MyClass* obj = arena.construct<MyClass>(arg1, arg2);
* // Construct trivially destructible objects in-place
* int* num = arena.construct<int>(42);
* MyPOD* obj = arena.construct<MyPOD>(arg1, arg2); // If MyPOD is trivial
*
* // Track memory usage
* size_t total = arena.total_allocated();
@@ -231,23 +233,36 @@ public:
* This is a convenience method that combines allocation with in-place
* construction. It properly handles alignment requirements for type T.
*
* @tparam T The type of object to construct
* @tparam T The type of object to construct (must be trivially destructible)
* @tparam Args Types of constructor arguments
* @param args Arguments to forward to T's constructor
* @return Pointer to the constructed object
* @throws std::bad_alloc if memory allocation fails
*
* ## Type Requirements:
* T must be trivially destructible (std::is_trivially_destructible_v<T>).
* This prevents subtle bugs since destructors are never called for objects
* constructed in the arena.
*
* ## Example:
* ```cpp
* std::string* str = arena.construct<std::string>("Hello, World!");
* MyClass* obj = arena.construct<MyClass>(arg1, arg2, arg3);
* int* num = arena.construct<int>(42); // ✓ Trivially
* destructible MyPOD* pod = arena.construct<MyPOD>(arg1, arg2); // ✓ If
* MyPOD is trivial std::string* str = arena.construct<std::string>("hi"); //
* ✗ Compile error!
* ```
*
* ## Note:
* Objects constructed this way cannot be individually destroyed.
* Their destructors will NOT be called automatically.
* Their destructors will NOT be called automatically - hence the requirement
* for trivially destructible types.
*/
template <typename T, typename... Args> T *construct(Args &&...args) {
static_assert(
std::is_trivially_destructible_v<T>,
"ArenaAllocator::construct requires trivially destructible types. "
"Objects constructed in the arena will not have their destructors "
"called.");
void *ptr = allocate(sizeof(T), alignof(T));
return new (ptr) T(std::forward<Args>(args)...);
}