123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- #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;
- template <typename T>
- struct allocator {
- using value_type = T;
- using size_type = std::size_t;
- using difference_type = std::ptrdiff_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 __helpers
- template <typename Allocator>
- struct allocator_traits {
- using allocator_type = Allocator;
- using value_type = typename Allocator::value_type;
- using pointer = value_type*;
- using size_type = std::size_t;
- 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
|