// -*-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 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 constexpr allocator(const allocator&) 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(::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 void construct(U* p, Args&&... args) { ::new (static_cast(p)) U(ctl::forward(args)...); } template void destroy(U* p) { p->~U(); } size_type max_size() const noexcept { return __SIZE_MAX__ / sizeof(T); } allocator& operator=(const allocator&) = default; template struct rebind { using other = allocator; }; }; template bool operator==(const allocator&, const allocator&) noexcept { return true; } template bool operator!=(const allocator&, const allocator&) noexcept { return false; } } // namespace ctl #endif // CTL_ALLOCATOR_H_