memory 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #ifndef __GBLIBCPP_MEMORY__
  2. #define __GBLIBCPP_MEMORY__
  3. #include <cstddef>
  4. #include <type_traits>
  5. #include <utility>
  6. namespace std {
  7. template <typename T>
  8. constexpr T* addressof(T& arg) noexcept
  9. {
  10. return __builtin_addressof(arg);
  11. }
  12. // template <typename T>
  13. // constexpr enable_if_t<is_function_v<remove_reference_t<T>>, T*>
  14. // addressof(T& arg) noexcept
  15. // {
  16. // return &arg;
  17. // }
  18. // template <typename T>
  19. // constexpr enable_if_t<!is_function_v<remove_reference_t<T>>, T*>
  20. // addressof(T& arg) noexcept
  21. // {
  22. // return reinterpret_cast<T*>(
  23. // &const_cast<char&>(
  24. // reinterpret_cast<const volatile char&>(arg)
  25. // )
  26. // );
  27. // }
  28. template <typename T>
  29. const T* addressof(const T&&) = delete;
  30. namespace __helpers {
  31. template <typename Alloc, typename = void>
  32. struct allocator_pointer
  33. { using type = std::add_pointer_t<typename Alloc::value_type>; };
  34. template <typename Alloc>
  35. struct allocator_pointer<Alloc,
  36. std::void_t<typename Alloc::pointer>>
  37. { using type = typename Alloc::pointer; };
  38. template <typename Alloc>
  39. using allocator_pointer_t =
  40. typename allocator_pointer<Alloc>::type;
  41. template <typename Alloc, typename = void>
  42. struct allocator_difference_type
  43. { using type = std::ptrdiff_t; };
  44. template <typename Alloc>
  45. struct allocator_difference_type<Alloc,
  46. std::void_t<typename Alloc::difference_type>>
  47. { using type = typename Alloc::difference_type; };
  48. template <typename Alloc>
  49. using allocator_difference_type_t =
  50. typename allocator_difference_type<Alloc>::type;
  51. template <typename Alloc, typename = void>
  52. struct allocator_size_type
  53. { using type = std::size_t; };
  54. template <typename Alloc>
  55. struct allocator_size_type<Alloc,
  56. std::void_t<typename Alloc::size_type>>
  57. { using type = typename Alloc::size_type; };
  58. template <typename Alloc>
  59. using allocator_size_type_t =
  60. typename allocator_size_type<Alloc>::type;
  61. template <typename Alloc, typename = void>
  62. struct allocator_prop_copy
  63. { using type = std::false_type; };
  64. template <typename Alloc>
  65. struct allocator_prop_copy<Alloc,
  66. std::void_t<typename Alloc::propagate_on_container_copy_assignment>>
  67. { using type = typename Alloc::propagate_on_container_copy_assignment; };
  68. template <typename Alloc>
  69. using allocator_prop_copy_t =
  70. typename allocator_prop_copy<Alloc>::type;
  71. template <typename Alloc, typename = void>
  72. struct allocator_prop_move
  73. { using type = std::false_type; };
  74. template <typename Alloc>
  75. struct allocator_prop_move<Alloc,
  76. std::void_t<typename Alloc::propagate_on_container_move_assignment>>
  77. { using type = typename Alloc::propagate_on_container_move_assignment; };
  78. template <typename Alloc>
  79. using allocator_prop_move_t =
  80. typename allocator_prop_move<Alloc>::type;
  81. template <typename Alloc, typename = void>
  82. struct allocator_prop_swap
  83. { using type = std::false_type; };
  84. template <typename Alloc>
  85. struct allocator_prop_swap<Alloc,
  86. std::void_t<typename Alloc::propagate_on_container_swap>>
  87. { using type = typename Alloc::propagate_on_container_swap; };
  88. template <typename Alloc>
  89. using allocator_prop_swap_t =
  90. typename allocator_prop_swap<Alloc>::type;
  91. } // namespace __helpers
  92. template <typename T>
  93. struct allocator {
  94. using value_type = T;
  95. constexpr allocator() noexcept = default;
  96. constexpr allocator(const allocator& other) noexcept = default;
  97. template <typename U>
  98. constexpr allocator(const allocator<U>&) noexcept {}
  99. constexpr ~allocator() = default;
  100. // throws std::bad_alloc
  101. [[nodiscard]] constexpr T* allocate(std::size_t n)
  102. { return static_cast<T*>(::operator new(n * sizeof(T))); }
  103. // TODO: check allocated size
  104. constexpr void deallocate(T* ptr, std::size_t)
  105. { ::operator delete(ptr); }
  106. };
  107. template <typename T1, typename T2>
  108. constexpr bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
  109. { return true; }
  110. template <typename T, typename... Args>
  111. constexpr std::enable_if_t<std::is_same_v<T*,
  112. decltype(::new(std::declval<void*>()) T(std::declval<Args>()...))> , T*>
  113. construct_at(T* p, Args&&... args)
  114. {
  115. return ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
  116. }
  117. template <typename T>
  118. constexpr void destroy_at(T* p)
  119. {
  120. // TODO: destroy array
  121. p->~T();
  122. }
  123. namespace __helpers {
  124. template <typename Allocator, typename T>
  125. struct rebind;
  126. template <template <typename, typename...> typename Allocator,
  127. typename NewType, typename OldType, typename... Args>
  128. struct rebind<Allocator<OldType, Args...>, NewType> {
  129. using type = Allocator<NewType, Args...>;
  130. };
  131. } // namespace __helpers
  132. template <typename Allocator>
  133. struct allocator_traits {
  134. using allocator_type = Allocator;
  135. using value_type = typename Allocator::value_type;
  136. using pointer =
  137. __helpers::allocator_pointer_t<Allocator>;
  138. using difference_type =
  139. __helpers::allocator_difference_type_t<Allocator>;
  140. using size_type =
  141. __helpers::allocator_size_type_t<Allocator>;
  142. using propagate_on_container_copy_assignment =
  143. __helpers::allocator_prop_copy_t<Allocator>;
  144. using propagate_on_container_move_assignment =
  145. __helpers::allocator_prop_move_t<Allocator>;
  146. using propagate_on_container_swap =
  147. __helpers::allocator_prop_swap_t<Allocator>;
  148. template <typename T>
  149. using rebind_alloc = typename __helpers::rebind<Allocator, T>::type;
  150. [[nodiscard]] static constexpr pointer allocate(Allocator& alloc, size_type n)
  151. { return alloc.allocate(n); }
  152. static constexpr void deallocate(Allocator& alloc, pointer p, size_type n)
  153. { return alloc.deallocate(p, n); }
  154. template <typename T, typename... Args>
  155. static constexpr void construct(Allocator&, T* p, Args&&... args)
  156. { std::construct_at(p, std::forward<Args>(args)...); }
  157. template <typename T>
  158. static constexpr void destroy(Allocator&, T* p)
  159. { std::destroy_at(p); }
  160. };
  161. } // namespace std
  162. #endif