// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- // vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi #ifndef CTL_ALLOCATOR_H_ #define CTL_ALLOCATOR_H_ #include "bad_alloc.h" #include "integral_constant.h" #include "new.h" #include "utility.h" namespace ctl { template<typename T> class allocator { public: using value_type = T; using size_type = size_t; using difference_type = ptrdiff_t; using propagate_on_container_move_assignment = ctl::true_type; using is_always_equal = ctl::true_type; using pointer = T*; using const_pointer = const T*; using reference = T&; using const_reference = const T&; constexpr allocator() noexcept = default; constexpr allocator(const allocator&) noexcept = default; template<class U> constexpr allocator(const allocator<U>&) noexcept { } constexpr ~allocator() = default; [[nodiscard]] T* allocate(size_type n) { if (n > __SIZE_MAX__ / sizeof(T)) throw ctl::bad_alloc(); if (auto p = static_cast<T*>(::operator new( n * sizeof(T), ctl::align_val_t(alignof(T)), ctl::nothrow))) return p; throw ctl::bad_alloc(); } void deallocate(T* p, size_type n) noexcept { ::operator delete(p, n * sizeof(T), ctl::align_val_t(alignof(T))); } template<typename U, typename... Args> void construct(U* p, Args&&... args) { ::new (static_cast<void*>(p)) U(ctl::forward<Args>(args)...); } template<typename U> void destroy(U* p) { p->~U(); } size_type max_size() const noexcept { return __SIZE_MAX__ / sizeof(T); } allocator& operator=(const allocator&) = default; template<typename U> struct rebind { using other = allocator<U>; }; }; template<class T, class U> bool operator==(const allocator<T>&, const allocator<U>&) noexcept { return true; } template<class T, class U> bool operator!=(const allocator<T>&, const allocator<U>&) noexcept { return false; } } // namespace ctl #endif // CTL_ALLOCATOR_H_