KTL
Loading...
Searching...
No Matches
type_allocator.h
Go to the documentation of this file.
1#pragma once
2
3#include "../utility/empty_base.h"
4#include "../utility/meta.h"
5#include "../utility/source_location.h"
6
8
9#include <memory>
10#include <type_traits>
11
12namespace ktl
13{
19 template<typename T, typename Alloc>
21 {
22 private:
23 static_assert(detail::has_no_value_type_v<Alloc>, "Building on top of typed allocators is not allowed. Use allocators without a type");
24 static_assert(!std::is_const_v<T>, "Using an allocator of const T is ill-formed");
25 static_assert(!std::is_copy_constructible_v<Alloc> || std::is_nothrow_copy_constructible_v<Alloc>, "Using a throwing copy constructor is ill-formed");
26 static_assert(!std::is_move_constructible_v<Alloc> || std::is_nothrow_move_constructible_v<Alloc>, "Using a throwing move constructor is ill-formed");
27 static_assert(!std::is_copy_assignable_v<Alloc> || std::is_nothrow_copy_assignable_v<Alloc>, "Using throwing copy assignment is ill-formed");
28 static_assert(!std::is_move_assignable_v<Alloc> || std::is_nothrow_move_assignable_v<Alloc>, "Using throwing move assignment is ill-formed");
29
30 template<typename U, typename A>
31 friend class type_allocator;
32
33 public:
34 typedef T value_type;
36 typedef std::false_type is_always_equal;
37
38 template<typename U>
39 struct rebind
40 {
42 };
43
48 type_allocator() = default;
49
53 template<typename... Args,
54 typename = std::enable_if_t<
55 std::is_constructible_v<Alloc, Args...>>>
56 explicit type_allocator(Args&&... alloc)
57 noexcept(std::is_nothrow_constructible_v<T, Args...>) :
58 m_Alloc(std::forward<Args>(alloc)...) {}
59
60 type_allocator(const type_allocator&) = default;
61
62 // Move construction is essentially forbidden for STL allocators
63 // A al(std::move(a)); a == al
64 // https://en.cppreference.com/w/cpp/named_req/Allocator
66 noexcept(std::is_nothrow_copy_constructible_v<Alloc>) :
67 m_Alloc(other.m_Alloc) {}
68
69 template<typename U>
71 noexcept(std::is_nothrow_constructible_v<Alloc, const type_allocator<U, Alloc>&>) :
72 m_Alloc(other.m_Alloc) {}
73
74 // Move construction is essentially forbidden for STL allocators
75 // https://en.cppreference.com/w/cpp/named_req/Allocator
76 template<typename U>
78 noexcept(std::is_nothrow_constructible_v<Alloc, type_allocator<U, Alloc>&&>) :
79 m_Alloc(other.m_Alloc) {}
80
82
83 // Move construction is essentially forbidden for STL allocators
84 // https://en.cppreference.com/w/cpp/named_req/Allocator
86 noexcept(std::is_nothrow_copy_assignable_v<Alloc>)
87 {
88 m_Alloc = rhs.m_Alloc;
89
90 return *this;
91 }
92
93#pragma region Allocation
99 value_type* allocate(size_t n, const source_location source = KTL_SOURCE())
100 noexcept(noexcept(m_Alloc.allocate(n)))
101 {
102 return reinterpret_cast<value_type*>(detail::allocate(m_Alloc, sizeof(value_type) * n, source));
103 }
104
110 void deallocate(value_type* p, size_t n)
111 noexcept(noexcept(m_Alloc.deallocate(p, n)))
112 {
113 m_Alloc.deallocate(p, sizeof(value_type) * n);
114 }
115#pragma endregion
116
117#pragma region Construction
125 template<typename... Args>
126 typename std::enable_if<detail::has_construct_v<Alloc, value_type*, Args...>, void>::type
127 construct(value_type* p, Args&&... args)
128 noexcept(detail::has_nothrow_construct_v<Alloc, value_type*, Args...>)
129 {
130 m_Alloc.construct(p, std::forward<Args>(args)...);
131 }
132
138 template<typename A = Alloc>
139 typename std::enable_if<detail::has_destroy_v<A, value_type*>, void>::type
142 {
143 m_Alloc.destroy(p);
144 }
145#pragma endregion
146
147#pragma region Utility
153 template<typename A = Alloc>
154 typename std::enable_if<detail::has_max_size_v<A>, size_type>::type
155 max_size() const
156 noexcept(detail::has_nothrow_max_size_v<A>)
157 {
158 return m_Alloc.max_size() / sizeof(T);
159 }
160
167 template<typename A = Alloc>
168 typename std::enable_if<detail::has_owns_v<A>, bool>::type
169 owns(value_type* p) const
171 {
172 return m_Alloc.owns(p);
173 }
174#pragma endregion
175
180 Alloc& get_allocator() noexcept
181 {
182 return m_Alloc;
183 }
184
189 const Alloc& get_allocator() const noexcept
190 {
191 return m_Alloc;
192 }
193
194 private:
195 KTL_EMPTY_BASE Alloc m_Alloc;
196 };
197
198 template<typename T, typename U, typename Alloc>
201 {
202 return lhs.get_allocator() == rhs.get_allocator();
203 }
204
205 template<typename T, typename U, typename Alloc>
208 {
209 return lhs.get_allocator() != rhs.get_allocator();
210 }
211}
Wrapper class for making an untyped allocator into a typed allocator.
Definition type_allocator.h:21
std::enable_if< detail::has_destroy_v< A, value_type * >, void >::type destroy(value_type *p) noexcept(detail::has_nothrow_destroy_v< Alloc, value_type * >)
Destructs an object of T at the given location.
Definition type_allocator.h:140
type_allocator(type_allocator &&other) noexcept(std::is_nothrow_copy_constructible_v< Alloc >)
Definition type_allocator.h:65
std::enable_if< detail::has_max_size_v< A >, size_type >::type max_size() const noexcept(detail::has_nothrow_max_size_v< A >)
Returns the maximum size that an allocation of objects can be.
Definition type_allocator.h:155
detail::get_size_type_t< Alloc > size_type
Definition type_allocator.h:35
type_allocator(type_allocator< U, Alloc > &&other) noexcept(std::is_nothrow_constructible_v< Alloc, type_allocator< U, Alloc > && >)
Definition type_allocator.h:77
std::false_type is_always_equal
Definition type_allocator.h:36
value_type * allocate(size_t n, const source_location source=KTL_SOURCE()) noexcept(noexcept(m_Alloc.allocate(n)))
Attempts to allocate a chunk of memory defined by n.
Definition type_allocator.h:99
std::enable_if< detail::has_construct_v< Alloc, value_type *, Args... >, void >::type construct(value_type *p, Args &&... args) noexcept(detail::has_nothrow_construct_v< Alloc, value_type *, Args... >)
Constructs an object of T with the given ...args at the given location.
Definition type_allocator.h:127
type_allocator()=default
Default constructor.
Alloc & get_allocator() noexcept
Returns a reference to the underlying allocator.
Definition type_allocator.h:180
void deallocate(value_type *p, size_t n) noexcept(noexcept(m_Alloc.deallocate(p, n)))
Attempts to deallocate the memory at location p.
Definition type_allocator.h:110
type_allocator(const type_allocator< U, Alloc > &other) noexcept(std::is_nothrow_constructible_v< Alloc, const type_allocator< U, Alloc > & >)
Definition type_allocator.h:70
type_allocator(const type_allocator &)=default
T value_type
Definition type_allocator.h:34
const Alloc & get_allocator() const noexcept
Returns a const reference to the underlying allocator.
Definition type_allocator.h:189
type_allocator & operator=(const type_allocator &)=default
type_allocator & operator=(type_allocator &&rhs) noexcept(std::is_nothrow_copy_assignable_v< Alloc >)
Definition type_allocator.h:85
std::enable_if< detail::has_owns_v< A >, bool >::type owns(value_type *p) const noexcept(detail::has_nothrow_owns_v< A >)
Returns whether or not the allocator owns the given location in memory.
Definition type_allocator.h:169
type_allocator(Args &&... alloc) noexcept(std::is_nothrow_constructible_v< T, Args... >)
Constructor for forwarding any arguments to the underlying allocator.
Definition type_allocator.h:56
#define KTL_EMPTY_BASE
Definition empty_base.h:6
typename get_size_type< Alloc, void >::type get_size_type_t
Definition meta.h:33
constexpr bool has_nothrow_construct_v
Definition meta.h:123
constexpr bool has_construct_v
Definition meta.h:53
void * allocate(Alloc &alloc, size_t n, const source_location source) noexcept(false)
Definition meta.h:161
constexpr bool has_no_value_type_v
Definition meta.h:17
Definition cascading.h:16
bool operator!=(const type_allocator< T, Alloc > &lhs, const type_allocator< U, Alloc > &rhs) noexcept(detail::has_nothrow_not_equal_v< Alloc >)
Definition type_allocator.h:206
bool operator==(const type_allocator< T, Alloc > &lhs, const type_allocator< U, Alloc > &rhs) noexcept(detail::has_nothrow_equal_v< Alloc >)
Definition type_allocator.h:199
#define KTL_SOURCE()
Definition source_location.h:11
Definition source_location.h:19
Definition type_allocator.h:40
type_allocator< U, Alloc > other
Definition type_allocator.h:41