/** This file is a part of rexy's general purpose library Copyright (C) 2020 rexy712 This program 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 3 of the License, or (at your option) any later version. This program 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 this program. If not, see . */ #ifndef REXY_DEFAULT_ALLOCATOR_HPP #define REXY_DEFAULT_ALLOCATOR_HPP #include //size_t #include //true_type, false_type #include #include //numeric_limits namespace rexy{ template struct allocator { using pointer = T*; using const_pointer = const T*; using void_pointer = void*; using const_void_pointer = const void*; using value_type = T; using size_type = size_t; using difference_type = ptrdiff_t; using is_always_equal = std::true_type; using propagate_on_container_copy_assignment = std::false_type; using propagate_on_container_move_assignment = std::false_type; using propagate_on_container_swap = std::false_type; template struct rebind{ using other = allocator; }; private: constexpr bool has_overflow(size_type n)const{ return n > max_size(); } public: allocator(void) = default; allocator(const allocator&) = default; allocator(allocator&&) = default; template constexpr allocator(const allocator&)noexcept{} ~allocator(void) = default; pointer allocate(size_type n){ size_type bytes = has_overflow(n) ? std::numeric_limits::max() : n*sizeof(T); if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){ return reinterpret_cast(::operator new(bytes)); }else{ return reinterpret_cast(::operator new(bytes, static_cast(alignof(T)))); } } void deallocate(pointer p, size_type n){ #if defined(__clang__) && !defined(__cpp_sized_deallocation) //clang does not enable ::operator delete(void* ptr, std::size_t sz) by default for some reason if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){ ::operator delete(p); }else{ ::operator delete(p, static_cast(alignof(T))); } #else size_type bytes = has_overflow(n) ? std::numeric_limits::max() : n*sizeof(T); if constexpr(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__){ ::operator delete(p, bytes); }else{ ::operator delete(p, bytes, static_cast(alignof(T))); } #endif } constexpr size_type max_size(void)const{ return std::numeric_limits::max()/sizeof(T); } }; template constexpr bool operator==(const allocator&, const allocator&){ return true; } template constexpr bool operator!=(const allocator&, const allocator&){ return false; } } #endif