/* * * The MIT License (MIT) * * Copyright (c) 2015 Charles Salvia * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ #include #include #include #include using namespace std; #ifndef INCLUDE_STACK_ALLOCATOR_HPP #define INCLUDE_STACK_ALLOCATOR_HPP template > class stack_allocator { public: typedef typename std::allocator_traits::value_type value_type; typedef typename std::allocator_traits::pointer pointer; typedef typename std::allocator_traits::const_pointer const_pointer; typedef typename Allocator::reference reference; typedef typename Allocator::const_reference const_reference; typedef typename std::allocator_traits::size_type size_type; typedef typename std::allocator_traits::difference_type difference_type; typedef typename std::allocator_traits::const_void_pointer const_void_pointer; typedef Allocator allocator_type; public: explicit stack_allocator(const allocator_type& alloc = allocator_type()) : m_allocator(alloc), m_begin(nullptr), m_end(nullptr), m_stack_pointer(nullptr) { } explicit stack_allocator(pointer buffer, const allocator_type& alloc = allocator_type()) : m_allocator(alloc), m_begin(buffer), m_end(buffer + N), m_stack_pointer(buffer) { } template stack_allocator(const stack_allocator& other) : m_allocator(other.m_allocator), m_begin(other.m_begin), m_end(other.m_end), m_stack_pointer(other.m_stack_pointer) { } constexpr static size_type capacity() { return N; } pointer allocate(size_type n, const_void_pointer hint = const_void_pointer()) { if (n <= size_type(std::distance(m_stack_pointer, m_end))) { pointer result = m_stack_pointer; m_stack_pointer += n; return result; } return m_allocator.allocate(n, hint); } void deallocate(pointer p, size_type n) { if (pointer_to_internal_buffer(p)) { m_stack_pointer -= n; } else m_allocator.deallocate(p, n); } size_type max_size() const noexcept { return m_allocator.max_size(); } template void construct(U* p, Args&&... args) { m_allocator.construct(p, std::forward(args)...); } template void destroy(U* p) { m_allocator.destroy(p); } pointer address(reference x) const noexcept { if (pointer_to_internal_buffer(std::addressof(x))) { return std::addressof(x); } return m_allocator.address(x); } const_pointer address(const_reference x) const noexcept { if (pointer_to_internal_buffer(std::addressof(x))) { return std::addressof(x); } return m_allocator.address(x); } template struct rebind { typedef stack_allocator other; }; pointer buffer() const noexcept { return m_begin; } private: bool pointer_to_internal_buffer(const_pointer p) const { return (!(std::less()(p, m_begin)) && (std::less()(p, m_end))); } allocator_type m_allocator; pointer m_begin; pointer m_end; pointer m_stack_pointer; }; template bool operator == (const stack_allocator& lhs, const stack_allocator& rhs) noexcept { return lhs.buffer() == rhs.buffer(); } template bool operator != (const stack_allocator& lhs, const stack_allocator& rhs) noexcept { return !(lhs == rhs); } // -------- Specialization for void // template class stack_allocator { public: typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef void* pointer; typedef const void* const_pointer; typedef void value_type; constexpr pointer buffer() const noexcept { return nullptr; } template struct rebind { typedef stack_allocator::other> other; }; }; #endif