source: mainline/uspace/lib/cpp/include/__bits/memory/allocator_traits.hpp

Last change on this file was b57a3ee, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: refactored the library layout, everything from the impl directory was moved to the bits directory for the sake of consistency, updated copyright notices and include guards

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_BITS_MEMORY_ALLOCATOR_TRAITS
30#define LIBCPP_BITS_MEMORY_ALLOCATOR_TRAITS
31
32#include <__bits/aux.hpp>
33#include <__bits/memory/addressof.hpp>
34#include <__bits/memory/pointer_traits.hpp>
35#include <__bits/memory/type_getters.hpp>
36#include <cstddef>
37#include <limits>
38#include <type_traits>
39
40namespace std
41{
42 /**
43 * 20.7.7, uses_allocator:
44 */
45
46 namespace aux
47 {
48 template<class T, class = void>
49 struct has_allocator_type: false_type
50 { /* DUMMY BODY */ };
51
52 template<class T>
53 struct has_allocator_type<T, void_t<typename T::allocator_type>>
54 : true_type
55 { /* DUMMY BODY */ };
56 }
57
58 template<class T, class Alloc>
59 struct uses_allocator
60 : aux::value_is<
61 bool, aux::has_allocator_type<T>::value && is_convertible_v<
62 Alloc, typename T::allocator_type
63 >
64 >
65 { /* DUMMY BODY */ };
66
67 /**
68 * 20.7.8, allocator traits:
69 */
70
71 template<class Alloc>
72 struct allocator_traits
73 {
74 using allocator_type = Alloc;
75
76 using value_type = typename Alloc::value_type;
77 using pointer = typename aux::alloc_get_pointer<Alloc>::type;
78 using const_pointer = typename aux::alloc_get_const_pointer<Alloc, pointer>::type;
79 using void_pointer = typename aux::alloc_get_void_pointer<Alloc, pointer>::type;
80 using const_void_pointer = typename aux::alloc_get_const_void_pointer<Alloc, pointer>::type;
81 using difference_type = typename aux::alloc_get_difference_type<Alloc, pointer>::type;
82 using size_type = typename aux::alloc_get_size_type<Alloc, difference_type>::type;
83
84 using propagate_on_container_copy_assignment = typename aux::alloc_get_copy_propagate<Alloc>::type;
85 using propagate_on_container_move_assignment = typename aux::alloc_get_move_propagate<Alloc>::type;
86 using propagate_on_container_swap = typename aux::alloc_get_swap_propagate<Alloc>::type;
87 using is_always_equal = typename aux::alloc_get_always_equal<Alloc>::type;
88
89 template<class T>
90 using rebind_alloc = typename aux::alloc_get_rebind_alloc<Alloc, T>;
91
92 template<class T>
93 using rebind_traits = allocator_traits<rebind_alloc<T>>;
94
95 static pointer allocate(Alloc& alloc, size_type n)
96 {
97 return alloc.allocate(n);
98 }
99
100 static pointer allocate(Alloc& alloc, size_type n, const_void_pointer hint)
101 {
102 if constexpr (aux::alloc_has_hint_allocate<Alloc, size_type, const_void_pointer>::value)
103 return alloc.allocate(n, hint);
104 else
105 return alloc.allocate(n);
106 }
107
108 static void deallocate(Alloc& alloc, pointer ptr, size_type n)
109 {
110 alloc.deallocate(ptr, n);
111 }
112
113 template<class T, class... Args>
114 static void construct(Alloc& alloc, T* ptr, Args&&... args)
115 {
116 if constexpr (aux::alloc_has_construct<Alloc, T, Args...>::value)
117 alloc.construct(ptr, forward<Args>(args)...);
118 else
119 ::new(static_cast<void*>(ptr)) T(forward<Args>(args)...);
120 }
121
122 template<class T>
123 static void destroy(Alloc& alloc, T* ptr)
124 {
125 if constexpr (aux::alloc_has_destroy<Alloc, T>::value)
126 alloc.destroy(ptr);
127 else
128 ptr->~T();
129 }
130
131 static size_type max_size(const Alloc& alloc) noexcept
132 {
133 if constexpr (aux::alloc_has_max_size<Alloc>::value)
134 return alloc.max_size();
135 else
136 return numeric_limits<size_type>::max();
137 }
138
139 static Alloc select_on_container_copy_construction(const Alloc& alloc)
140 {
141 if constexpr (aux::alloc_has_select<Alloc>::value)
142 return alloc.select_on_container_copy_construction();
143 else
144 return alloc;
145 }
146 };
147
148 /**
149 * 20.7.9, the default allocator
150 */
151
152 template<class T>
153 class allocator;
154
155 template<>
156 class allocator<void>
157 {
158 public:
159 using pointer = void*;
160 using const_pointer = const void*;
161 using value_type = void;
162
163 template<class U>
164 struct rebind
165 {
166 using other = allocator<U>;
167 };
168 };
169
170 template<class T>
171 T* addressof(T& x) noexcept;
172
173 template<class T>
174 class allocator
175 {
176 public:
177 using size_type = size_t;
178 using difference_type = ptrdiff_t;
179 using pointer = T*;
180 using const_pointer = const T*;
181 using reference = T&;
182 using const_reference = const T&;
183 using value_type = T;
184
185 template<class U>
186 struct rebind
187 {
188 using other = allocator<U>;
189 };
190
191 using propagate_on_container_move_assignment = true_type;
192 using is_always_equal = true_type;
193
194 allocator() noexcept = default;
195
196 allocator(const allocator&) noexcept = default;
197
198 template<class U>
199 allocator(const allocator<U>&) noexcept
200 { /* DUMMY BODY */ }
201
202 ~allocator() = default;
203
204 pointer address(reference x) const noexcept
205 {
206 return addressof(x);
207 }
208
209 const_pointer address(const_reference x) const noexcept
210 {
211 return addressof(x);
212 }
213
214 pointer allocate(size_type n, allocator<void>::const_pointer = 0)
215 {
216 return static_cast<pointer>(::operator new(n * sizeof(value_type)));
217 }
218
219 void deallocate(pointer ptr, size_type n)
220 {
221 ::operator delete(ptr, n);
222 }
223
224 size_type max_size() const noexcept
225 {
226 return numeric_limits<size_type>::max();
227 }
228
229 template<class U, class... Args>
230 void construct(U* ptr, Args&&... args)
231 {
232 ::new((void*)ptr) U(forward<Args>(args)...);
233 }
234
235 template<class U>
236 void destroy(U* ptr)
237 {
238 ptr->~U();
239 }
240 };
241
242 template<class T1, class T2>
243 bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
244 {
245 return true;
246 }
247
248 template<class T1, class T2>
249 bool operator!=(const allocator<T1>&, const allocator<T2>&) noexcept
250 {
251 return false;
252 }
253}
254
255#endif
Note: See TracBrowser for help on using the repository browser.