/* Copyright (C) 2026 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * 0 A.D. is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 0 A.D. If not, see . */ #ifndef INCLUDED_PS_ALLOCATORADAPTER #define INCLUDED_PS_ALLOCATORADAPTER #include #include #include namespace PS::Memory { /** * Provides a way to use untyped allocators like LinearAllocator for * containers. This allocator adapter must not outlive the target * allocator. A client must not mix adapters with different * allocators. * * It provides a basic STL allocator interface. It allows to use a stateful * allocator: * * std::vector> * * @see ScopedLinearAllocator */ template class AllocatorAdapter { public: using value_type = T; // We don't need runtime checks and per-element copies for containers // when we have a unique allocator (means no mixing different allocators). using propagate_on_container_copy_assignment = std::true_type; using propagate_on_container_move_assignment = std::true_type; using propagate_on_container_swap = std::true_type; using is_always_equal = std::false_type; template struct rebind { using other = AllocatorAdapter; }; constexpr AllocatorAdapter(Allocator& allocator) noexcept : m_Allocator(std::addressof(allocator)) {} template constexpr AllocatorAdapter(const AllocatorAdapter& allocatorAdapter) noexcept : m_Allocator(allocatorAdapter.m_Allocator) {} [[nodiscard]] constexpr T* allocate(std::size_t n) { return static_cast(m_Allocator->allocate(n * sizeof(T), alignof(T))); } constexpr void deallocate(T* ptr, std::size_t n) { m_Allocator->deallocate(static_cast(ptr), n * sizeof(T)); } template constexpr bool operator==(const AllocatorAdapter& other) const noexcept { return m_Allocator == other.m_Allocator; } private: template friend class AllocatorAdapter; // A pointer to make it moveable. Allocator* m_Allocator{nullptr}; }; } // namespace PS::Memory #endif // INCLUDED_PS_ALLOCATORADAPTER