memory 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. template <typename T>
  31. struct allocator {
  32. using value_type = T;
  33. using size_type = std::size_t;
  34. using difference_type = std::ptrdiff_t;
  35. constexpr allocator() noexcept = default;
  36. constexpr allocator(const allocator& other) noexcept = default;
  37. template <typename U>
  38. constexpr allocator(const allocator<U>&) noexcept {}
  39. constexpr ~allocator() = default;
  40. // throws std::bad_alloc
  41. [[nodiscard]] constexpr T* allocate(std::size_t n)
  42. { return static_cast<T*>(::operator new(n * sizeof(T))); }
  43. // TODO: check allocated size
  44. constexpr void deallocate(T* ptr, std::size_t)
  45. { ::operator delete(ptr); }
  46. };
  47. template <typename T1, typename T2>
  48. constexpr bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
  49. { return true; }
  50. template <typename T, typename... Args>
  51. constexpr std::enable_if_t<std::is_same_v<T*,
  52. decltype(::new(std::declval<void*>()) T(std::declval<Args>()...))> , T*>
  53. construct_at(T* p, Args&&... args)
  54. {
  55. return ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
  56. }
  57. template <typename T>
  58. constexpr void destroy_at(T* p)
  59. {
  60. // TODO: destroy array
  61. p->~T();
  62. }
  63. namespace __helpers {
  64. template <typename Allocator, typename T>
  65. struct rebind;
  66. template <template <typename, typename...> typename Allocator,
  67. typename NewType, typename OldType, typename... Args>
  68. struct rebind<Allocator<OldType, Args...>, NewType> {
  69. using type = Allocator<NewType, Args...>;
  70. };
  71. } // namespace __helpers
  72. template <typename Allocator>
  73. struct allocator_traits {
  74. using allocator_type = Allocator;
  75. using value_type = typename Allocator::value_type;
  76. using pointer = value_type*;
  77. using size_type = std::size_t;
  78. template <typename T>
  79. using rebind_alloc = typename __helpers::rebind<Allocator, T>::type;
  80. [[nodiscard]] static constexpr pointer allocate(Allocator& alloc, size_type n)
  81. { return alloc.allocate(n); }
  82. static constexpr void deallocate(Allocator& alloc, pointer p, size_type n)
  83. { return alloc.deallocate(p, n); }
  84. template <typename T, typename... Args>
  85. static constexpr void construct(Allocator&, T* p, Args&&... args)
  86. { std::construct_at(p, std::forward<Args>(args)...); }
  87. template <typename T>
  88. static constexpr void destroy(Allocator&, T* p)
  89. { std::destroy_at(p); }
  90. };
  91. } // namespace std
  92. #endif