source: mainline/uspace/lib/cpp/include/impl/memory.hpp@ 973a268

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 973a268 was 973a268, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added addressof

  • Property mode set to 100644
File size: 13.6 KB
Line 
1/*
2 * Copyright (c) 2017 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_MEMORY
30#define LIBCPP_MEMORY
31
32#include <internal/aux.hpp>
33#include <utility>
34#include <type_traits>
35
36namespace std
37{
38 /**
39 * 20.7.3, pointer traits:
40 */
41
42 template<class Ptr>
43 struct pointer_traits
44 {
45 using pointer = Ptr;
46 // TODO: element type, difference type
47
48 // TODO: this is conditional, see standard
49 template<class U>
50 using rebind = typename Ptr::template rebind<U>;
51 };
52
53 /**
54 * 20.7.8, allocator traits:
55 */
56
57 namespace aux
58 {
59 /**
60 * The standard mandates that we reuse type from allocators
61 * *if* they are defined or that we use something different.
62 * These structures help us alternate between those by
63 * using SFINAE.
64 * TODO: Create tests for these!
65 */
66
67 template<class T, class = void>
68 struct get_pointer: aux::type_is<typename T::value_type*>
69 { /* DUMMY BODY */ };
70
71 template<class T>
72 struct get_pointer<T, void_t<typename T::pointer>>
73 : aux::type_is<typename T::pointer>
74 { /* DUMMY BODY */ };
75
76 template<class T, class Ptr, class = void>
77 struct get_const_pointer
78 : aux::type_is<typename pointer_traits<Ptr>::template rebind<const typename T::value_type>>
79 { /* DUMMY BODY */ };
80
81 template<class T, class Ptr>
82 struct get_const_pointer<T, Ptr, void_t<typename T::const_pointer>>
83 : aux::type_is<typename T::const_pointer>
84 { /* DUMMY BODY */ };
85
86 template<class T, class Ptr, class = void>
87 struct get_void_pointer
88 : aux::type_is<typename pointer_traits<Ptr>::template rebind<void>>
89 { /* DUMMY BODY */ };
90
91 template<class T, class Ptr>
92 struct get_void_pointer<T, Ptr, void_t<typename T::void_pointer>>
93 : aux::type_is<typename T::void_pointer>
94 { /* DUMMY BODY */ };
95
96 template<class T, class Ptr, class = void>
97 struct get_const_void_pointer
98 : aux::type_is<typename pointer_traits<Ptr>::template rebind<const void>>
99 { /* DUMMY BODY */ };
100
101 template<class T, class Ptr>
102 struct get_const_void_pointer<T, Ptr, void_t<typename T::const_void_pointer>>
103 : aux::type_is<typename T::const_void_pointer>
104 { /* DUMMY BODY */ };
105
106 template<class T, class Ptr, class = void>
107 struct get_difference_type
108 : aux::type_is<typename pointer_traits<Ptr>::difference_type>
109 { /* DUMMY BODY */ };
110
111 template<class T, class Ptr>
112 struct get_difference_type<T, Ptr, void_t<typename T::difference_type>>
113 : aux::type_is<typename T::difference_type>
114 { /* DUMMY BODY */ };
115
116 template<class T, class Difference, class = void>
117 struct get_size_type: aux::type_is<make_unsigned_t<Difference>>
118 { /* DUMMY BODY */ };
119
120 template<class T, class Difference>
121 struct get_size_type<T, Difference, void_t<typename T::size_type>>
122 : aux::type_is<typename T::size_type>
123 { /* DUMMY BODY */ };
124
125 template<class T, class = void>
126 struct get_copy_propagate: aux::type_is<false_type>
127 { /* DUMMY BODY */ };
128
129 template<class T>
130 struct get_copy_propagate<T, void_t<typename T::propagate_on_container_copy_assignment>>
131 : aux::type_is<typename T::propagate_on_container_copy_assignment>
132 { /* DUMMY BODY */ };
133
134 template<class T, class = void>
135 struct get_move_propagate: aux::type_is<false_type>
136 { /* DUMMY BODY */ };
137
138 template<class T>
139 struct get_move_propagate<T, void_t<typename T::propagate_on_container_move_assignment>>
140 : aux::type_is<typename T::propagate_on_container_move_assignment>
141 { /* DUMMY BODY */ };
142
143 template<class T, class = void>
144 struct get_swap_propagate: aux::type_is<false_type>
145 { /* DUMMY BODY */ };
146
147 template<class T>
148 struct get_swap_propagate<T, void_t<typename T::propagate_on_container_swap>>
149 : aux::type_is<typename T::propagate_on_container_swap>
150 { /* DUMMY BODY */ };
151
152 template<class T, class = void>
153 struct get_always_equal: aux::type_is<typename is_empty<T>::type>
154 { /* DUMMY BODY */ };
155
156 template<class T>
157 struct get_always_equal<T, void_t<typename T::is_always_equal>>
158 : aux::type_is<typename T::is_always_equal>
159 { /* DUMMY BODY */ };
160
161 template<class Alloc, class T, class = void>
162 struct get_rebind_other
163 { /* DUMMY BODY */ };
164
165 template<class Alloc, class T>
166 struct get_rebind_other<Alloc, T, void_t<typename Alloc::template rebind<T>::other>>
167 : aux::type_is<typename Alloc::template rebind<T>::other>
168 { /* DUMMY BODY */ };
169
170 /* TODO: How am I suppose to do this?!
171 template<template<class T, class... Args> class Alloc>
172 struct get_rebind_args;
173 */
174
175 template<class Alloc, class T>
176 struct get_rebind_args: aux::type_is<typename get_rebind_other<Alloc, T>::type>
177 { /* DUMMY BODY */ };
178 }
179
180 template<class Alloc>
181 struct allocator_traits
182 {
183 using allocator_type = Alloc;
184
185 using value_type = typename Alloc::value_type;
186 using pointer = typename aux::get_pointer<Alloc>::type;
187 using const_pointer = typename aux::get_const_pointer<Alloc, pointer>::type;
188 // TODO: fix void pointer typedefs
189 /* using void_pointer = typename aux::get_void_pointer<Alloc, pointer>::type; */
190 /* using const_void_pointer = typename aux::get_const_void_pointer<Alloc, pointer>::type; */
191 using void_pointer = void*;
192 using const_void_pointer = const void*;
193 using difference_type = typename aux::get_difference_type<Alloc, pointer>::type;
194 using size_type = typename aux::get_size_type<Alloc, difference_type>::type;
195
196 using propagate_on_container_copy_assignment = typename aux::get_copy_propagate<Alloc>::type;
197 using propagate_on_container_move_assignment = typename aux::get_move_propagate<Alloc>::type;
198 using propagate_on_container_swap = typename aux::get_swap_propagate<Alloc>::type;
199 using is_always_equal = typename aux::get_always_equal<Alloc>::type;
200
201 template<class T>
202 using rebind_alloc = typename aux::get_rebind_args<Alloc, T>;
203
204 template<class T>
205 using rebind_traits = allocator_traits<rebind_alloc<T>>;
206
207 static pointer allocate(Alloc& alloc, size_type n)
208 {
209 return alloc.allocate(n);
210 }
211
212 static pointer allocate(Alloc& alloc, size_type n, const_void_pointer hint)
213 { // TODO: this when it's well formed, otherwise alloc.allocate(n)
214 return alloc.allocate(n, hint);
215 }
216
217 static void deallocate(Alloc& alloc, pointer ptr, size_type n)
218 {
219 alloc.deallocate(ptr, n);
220 }
221
222 template<class T, class... Args>
223 static void construct(Alloc& alloc, T* ptr, Args&&... args)
224 {
225 // TODO: implement
226 }
227
228 template<class T>
229 static void destroy(Alloc& alloc, T* ptr)
230 {
231 // TODO: implement
232 }
233
234 static size_type max_size(const Alloc& alloc) noexcept
235 {
236 // TODO: implement
237 return 0;
238 }
239
240 static Alloc select_on_container_copy_construction(const Alloc& alloc)
241 {
242 // TODO: implement
243 return Alloc{};
244 }
245 };
246
247 /**
248 * 20.7.9, the default allocator
249 */
250
251 template<class T>
252 class allocator;
253
254 template<>
255 class allocator<void>
256 {
257 public:
258 using pointer = void*;
259 using const_pointer = const void*;
260 using value_type = void;
261
262 template<class U>
263 struct rebind
264 {
265 using other = allocator<U>;
266 };
267 };
268
269 template<class T>
270 T* addressof(T& x) noexcept;
271
272 template<class T>
273 class allocator
274 {
275 public:
276 using size_type = size_t;
277 using difference_type = ptrdiff_t;
278 using pointer = T*;
279 using const_pointer = const T*;
280 using reference = T&;
281 using const_reference = const T&;
282 using value_type = T;
283
284 template<class U>
285 struct rebind
286 {
287 using other = allocator<U>;
288 };
289
290 using propagate_on_container_move_assignment = true_type;
291 using is_always_equal = true_type;
292
293 allocator() noexcept = default;
294
295 allocator(const allocator&) noexcept = default;
296
297 template<class U>
298 allocator(const allocator<U>&) noexcept
299 {
300 // TODO: implement
301 }
302
303 ~allocator() = default;
304
305 pointer address(reference x) const noexcept
306 {
307 return addressof(x);
308 }
309
310 const_pointer address(const_reference x) const noexcept
311 {
312 return addressof(x);
313 }
314
315 pointer allocate(size_type n, allocator<void>::const_pointer hint = 0)
316 {
317 /**
318 * Note: The usage of hint is unspecified.
319 * TODO: Check HelenOS hint allocation capabilities.
320 * TODO: assert that n < max_size()
321 */
322 return static_cast<pointer>(::operator new(n * sizeof(value_type)));
323 }
324
325 void deallocate(pointer ptr, size_type n)
326 {
327 ::operator delete(ptr, n);
328 }
329
330 size_type max_size() const noexcept
331 { // TODO: implement, max argument to allocate
332 return 0xFFFFFFFF;
333 }
334
335 template<class U, class... Args>
336 void construct(U* ptr, Args&&... args)
337 {
338 ::new((void*)ptr) U(forward<Args>(args)...);
339 }
340
341 template<class U>
342 void destroy(U* ptr)
343 {
344 ptr->~U();
345 }
346 };
347
348 template<class T1, class T2>
349 bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
350 {
351 return true;
352 }
353
354 template<class T1, class T2>
355 bool operator!=(const allocator<T1>&, const allocator<T2>&) noexcept
356 {
357 return false;
358 }
359
360 /**
361 * 20.7.10, raw storage iterator:
362 */
363
364 // TODO: implement
365
366 /**
367 * 20.7.11, temporary buffers:
368 */
369
370 // TODO: implement
371
372 /**
373 * 20.7.12, specialized algorithms:
374 */
375
376 template<class T>
377 T* addressof(T& x) noexcept
378 {
379 return reinterpret_cast<T*>(
380 &const_cast<char&>(
381 reinterpret_cast<const volatile char&>(x)
382 ));
383 }
384
385 template<class Iterator>
386 struct iterator_traits;
387
388 template<class InputIterator, class ForwardIterator>
389 ForwardIterator unitialized_copy(
390 InputIterator first, InputIterator last,
391 ForwardIterator result
392 )
393 {
394 for (; first != last; ++first, ++result)
395 ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first);
396
397 return result;
398 }
399
400 template<class InputIterator, class Size, class ForwardIterator>
401 ForwardIterator unitialized_copy_n(
402 InputIterator first, Size n, ForwardIterator result
403 )
404 {
405 for (; n > 0; ++first, --n, ++result)
406 ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first);
407
408 return result;
409 }
410
411 template<class ForwardIterator, class T>
412 void unitialized_fill(
413 ForwardIterator first, ForwardIterator last, const T& x
414 )
415 {
416 for (; first != last; ++first)
417 ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x);
418 }
419
420 template<class ForwardIterator, class Size, class T>
421 ForwardIterator unitialized_fill_n(
422 ForwardIterator first, Size n, const T& x
423 )
424 {
425 for (; n > 0; ++first, --n)
426 ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x);
427
428 return first;
429 }
430}
431
432#endif
Note: See TracBrowser for help on using the repository browser.