| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 | #ifndef __GBLIBCPP_MEMORY__#define __GBLIBCPP_MEMORY__#include <cstddef>#include <type_traits>#include <utility>namespace std {template <typename T>constexpr T* addressof(T& arg) noexcept{    return __builtin_addressof(arg);}// template <typename T>// constexpr enable_if_t<is_function_v<remove_reference_t<T>>, T*>// addressof(T& arg) noexcept// {//     return &arg;// }// template <typename T>// constexpr enable_if_t<!is_function_v<remove_reference_t<T>>, T*>// addressof(T& arg) noexcept// {//     return reinterpret_cast<T*>(//         &const_cast<char&>(//             reinterpret_cast<const volatile char&>(arg)//         )//     );// }template <typename T>const T* addressof(const T&&) = delete;namespace __helpers {template <typename Alloc, typename = void>struct allocator_pointer{ using type = std::add_pointer_t<typename Alloc::value_type>; };template <typename Alloc>struct allocator_pointer<Alloc,    std::void_t<typename Alloc::pointer>>{ using type = typename Alloc::pointer; };template <typename Alloc>using allocator_pointer_t =    typename allocator_pointer<Alloc>::type;template <typename Alloc, typename = void>struct allocator_difference_type{ using type = std::ptrdiff_t; };template <typename Alloc>struct allocator_difference_type<Alloc,    std::void_t<typename Alloc::difference_type>>{ using type = typename Alloc::difference_type; };template <typename Alloc>using allocator_difference_type_t =    typename allocator_difference_type<Alloc>::type;template <typename Alloc, typename = void>struct allocator_size_type{ using type = std::size_t; };template <typename Alloc>struct allocator_size_type<Alloc,    std::void_t<typename Alloc::size_type>>{ using type = typename Alloc::size_type; };template <typename Alloc>using allocator_size_type_t =    typename allocator_size_type<Alloc>::type;template <typename Alloc, typename = void>struct allocator_prop_copy{ using type = std::false_type; };template <typename Alloc>struct allocator_prop_copy<Alloc,    std::void_t<typename Alloc::propagate_on_container_copy_assignment>>{ using type = typename Alloc::propagate_on_container_copy_assignment; };template <typename Alloc>using allocator_prop_copy_t =    typename allocator_prop_copy<Alloc>::type;template <typename Alloc, typename = void>struct allocator_prop_move{ using type = std::false_type; };template <typename Alloc>struct allocator_prop_move<Alloc,    std::void_t<typename Alloc::propagate_on_container_move_assignment>>{ using type = typename Alloc::propagate_on_container_move_assignment; };template <typename Alloc>using allocator_prop_move_t =    typename allocator_prop_move<Alloc>::type;template <typename Alloc, typename = void>struct allocator_prop_swap{ using type = std::false_type; };template <typename Alloc>struct allocator_prop_swap<Alloc,    std::void_t<typename Alloc::propagate_on_container_swap>>{ using type = typename Alloc::propagate_on_container_swap; };template <typename Alloc>using allocator_prop_swap_t =    typename allocator_prop_swap<Alloc>::type;} // namespace __helperstemplate <typename T>struct allocator {    using value_type = T;    constexpr allocator() noexcept = default;    constexpr allocator(const allocator& other) noexcept = default;    template <typename U>    constexpr allocator(const allocator<U>&) noexcept {}    constexpr ~allocator() = default;    // throws std::bad_alloc    [[nodiscard]] constexpr T* allocate(std::size_t n)    { return static_cast<T*>(::operator new(n * sizeof(T))); }    // TODO: check allocated size    constexpr void deallocate(T* ptr, std::size_t)    { ::operator delete(ptr); }};template <typename T1, typename T2>constexpr bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept{ return true; }template <typename T, typename... Args>constexpr std::enable_if_t<std::is_same_v<T*,    decltype(::new(std::declval<void*>()) T(std::declval<Args>()...))> , T*>construct_at(T* p, Args&&... args){    return ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);}template <typename T>constexpr void destroy_at(T* p){    // TODO: destroy array    p->~T();}namespace __helpers {template <typename Allocator, typename T>struct rebind;template <template <typename, typename...> typename Allocator,    typename NewType, typename OldType, typename... Args>struct rebind<Allocator<OldType, Args...>, NewType> {    using type = Allocator<NewType, Args...>;};} // namespace __helperstemplate <typename Allocator>struct allocator_traits {    using allocator_type = Allocator;    using value_type = typename Allocator::value_type;    using pointer =        __helpers::allocator_pointer_t<Allocator>;    using difference_type =        __helpers::allocator_difference_type_t<Allocator>;    using size_type =        __helpers::allocator_size_type_t<Allocator>;    using propagate_on_container_copy_assignment =        __helpers::allocator_prop_copy_t<Allocator>;    using propagate_on_container_move_assignment =        __helpers::allocator_prop_move_t<Allocator>;    using propagate_on_container_swap =        __helpers::allocator_prop_swap_t<Allocator>;    template <typename T>    using rebind_alloc = typename __helpers::rebind<Allocator, T>::type;    [[nodiscard]] static constexpr pointer allocate(Allocator& alloc, size_type n)    { return alloc.allocate(n); }    static constexpr void deallocate(Allocator& alloc, pointer p, size_type n)    { return alloc.deallocate(p, n); }    template <typename T, typename... Args>    static constexpr void construct(Allocator&, T* p, Args&&... args)    { std::construct_at(p, std::forward<Args>(args)...); }    template <typename T>    static constexpr void destroy(Allocator&, T* p)    { std::destroy_at(p); }};} // namespace std#endif
 |