#ifndef __GBLIBCPP_MEMORY__ #define __GBLIBCPP_MEMORY__ #include #include #include namespace std { template constexpr T* addressof(T& arg) noexcept { return __builtin_addressof(arg); } // template // constexpr enable_if_t>, T*> // addressof(T& arg) noexcept // { // return &arg; // } // template // constexpr enable_if_t>, T*> // addressof(T& arg) noexcept // { // return reinterpret_cast( // &const_cast( // reinterpret_cast(arg) // ) // ); // } template const T* addressof(const T&&) = delete; namespace __helpers { template struct allocator_pointer { using type = std::add_pointer_t; }; template struct allocator_pointer> { using type = typename Alloc::pointer; }; template using allocator_pointer_t = typename allocator_pointer::type; template struct allocator_difference_type { using type = std::ptrdiff_t; }; template struct allocator_difference_type> { using type = typename Alloc::difference_type; }; template using allocator_difference_type_t = typename allocator_difference_type::type; template struct allocator_size_type { using type = std::size_t; }; template struct allocator_size_type> { using type = typename Alloc::size_type; }; template using allocator_size_type_t = typename allocator_size_type::type; template struct allocator_prop_copy { using type = std::false_type; }; template struct allocator_prop_copy> { using type = typename Alloc::propagate_on_container_copy_assignment; }; template using allocator_prop_copy_t = typename allocator_prop_copy::type; template struct allocator_prop_move { using type = std::false_type; }; template struct allocator_prop_move> { using type = typename Alloc::propagate_on_container_move_assignment; }; template using allocator_prop_move_t = typename allocator_prop_move::type; template struct allocator_prop_swap { using type = std::false_type; }; template struct allocator_prop_swap> { using type = typename Alloc::propagate_on_container_swap; }; template using allocator_prop_swap_t = typename allocator_prop_swap::type; } // namespace __helpers template struct allocator { using value_type = T; constexpr allocator() noexcept = default; constexpr allocator(const allocator& other) noexcept = default; template constexpr allocator(const allocator&) noexcept {} constexpr ~allocator() = default; // throws std::bad_alloc [[nodiscard]] constexpr T* allocate(std::size_t n) { return static_cast(::operator new(n * sizeof(T))); } // TODO: check allocated size constexpr void deallocate(T* ptr, std::size_t) { ::operator delete(ptr); } }; template constexpr bool operator==(const allocator&, const allocator&) noexcept { return true; } template constexpr std::enable_if_t()) T(std::declval()...))> , T*> construct_at(T* p, Args&&... args) { return ::new (static_cast(p)) T(std::forward(args)...); } template constexpr void destroy_at(T* p) { // TODO: destroy array p->~T(); } namespace __helpers { template struct rebind; template