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

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

cpp: added missing include

  • Property mode set to 100644
File size: 29.2 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 <new>
34#include <type_traits>
35#include <utility>
36
37namespace std
38{
39 /**
40 * 20.7.3, pointer traits:
41 */
42
43 template<class Ptr>
44 struct pointer_traits
45 {
46 using pointer = Ptr;
47 // TODO: element type, difference type
48
49 // TODO: this is conditional, see standard
50 template<class U>
51 using rebind = typename Ptr::template rebind<U>;
52 };
53
54 /**
55 * 20.7.8, allocator traits:
56 */
57
58 namespace aux
59 {
60 /**
61 * The standard mandates that we reuse type from allocators
62 * *if* they are defined or that we use something different.
63 * These structures help us alternate between those by
64 * using SFINAE.
65 * TODO: Create tests for these!
66 */
67
68 template<class T, class = void>
69 struct get_pointer: aux::type_is<typename T::value_type*>
70 { /* DUMMY BODY */ };
71
72 template<class T>
73 struct get_pointer<T, void_t<typename T::pointer>>
74 : aux::type_is<typename T::pointer>
75 { /* DUMMY BODY */ };
76
77 template<class T, class Ptr, class = void>
78 struct get_const_pointer
79 : aux::type_is<typename pointer_traits<Ptr>::template rebind<const typename T::value_type>>
80 { /* DUMMY BODY */ };
81
82 template<class T, class Ptr>
83 struct get_const_pointer<T, Ptr, void_t<typename T::const_pointer>>
84 : aux::type_is<typename T::const_pointer>
85 { /* DUMMY BODY */ };
86
87 template<class T, class Ptr, class = void>
88 struct get_void_pointer
89 : aux::type_is<typename pointer_traits<Ptr>::template rebind<void>>
90 { /* DUMMY BODY */ };
91
92 template<class T, class Ptr>
93 struct get_void_pointer<T, Ptr, void_t<typename T::void_pointer>>
94 : aux::type_is<typename T::void_pointer>
95 { /* DUMMY BODY */ };
96
97 template<class T, class Ptr, class = void>
98 struct get_const_void_pointer
99 : aux::type_is<typename pointer_traits<Ptr>::template rebind<const void>>
100 { /* DUMMY BODY */ };
101
102 template<class T, class Ptr>
103 struct get_const_void_pointer<T, Ptr, void_t<typename T::const_void_pointer>>
104 : aux::type_is<typename T::const_void_pointer>
105 { /* DUMMY BODY */ };
106
107 template<class T, class Ptr, class = void>
108 struct get_difference_type
109 : aux::type_is<typename pointer_traits<Ptr>::difference_type>
110 { /* DUMMY BODY */ };
111
112 template<class T, class Ptr>
113 struct get_difference_type<T, Ptr, void_t<typename T::difference_type>>
114 : aux::type_is<typename T::difference_type>
115 { /* DUMMY BODY */ };
116
117 template<class T, class Difference, class = void>
118 struct get_size_type: aux::type_is<make_unsigned_t<Difference>>
119 { /* DUMMY BODY */ };
120
121 template<class T, class Difference>
122 struct get_size_type<T, Difference, void_t<typename T::size_type>>
123 : aux::type_is<typename T::size_type>
124 { /* DUMMY BODY */ };
125
126 template<class T, class = void>
127 struct get_copy_propagate: aux::type_is<false_type>
128 { /* DUMMY BODY */ };
129
130 template<class T>
131 struct get_copy_propagate<T, void_t<typename T::propagate_on_container_copy_assignment>>
132 : aux::type_is<typename T::propagate_on_container_copy_assignment>
133 { /* DUMMY BODY */ };
134
135 template<class T, class = void>
136 struct get_move_propagate: aux::type_is<false_type>
137 { /* DUMMY BODY */ };
138
139 template<class T>
140 struct get_move_propagate<T, void_t<typename T::propagate_on_container_move_assignment>>
141 : aux::type_is<typename T::propagate_on_container_move_assignment>
142 { /* DUMMY BODY */ };
143
144 template<class T, class = void>
145 struct get_swap_propagate: aux::type_is<false_type>
146 { /* DUMMY BODY */ };
147
148 template<class T>
149 struct get_swap_propagate<T, void_t<typename T::propagate_on_container_swap>>
150 : aux::type_is<typename T::propagate_on_container_swap>
151 { /* DUMMY BODY */ };
152
153 template<class T, class = void>
154 struct get_always_equal: aux::type_is<typename is_empty<T>::type>
155 { /* DUMMY BODY */ };
156
157 template<class T>
158 struct get_always_equal<T, void_t<typename T::is_always_equal>>
159 : aux::type_is<typename T::is_always_equal>
160 { /* DUMMY BODY */ };
161
162 template<class Alloc, class T, class = void>
163 struct get_rebind_other
164 { /* DUMMY BODY */ };
165
166 template<class Alloc, class T>
167 struct get_rebind_other<Alloc, T, void_t<typename Alloc::template rebind<T>::other>>
168 : aux::type_is<typename Alloc::template rebind<T>::other>
169 { /* DUMMY BODY */ };
170
171 /* TODO: How am I suppose to do this?!
172 template<template<class T, class... Args> class Alloc>
173 struct get_rebind_args;
174 */
175
176 template<class Alloc, class T>
177 struct get_rebind_args: aux::type_is<typename get_rebind_other<Alloc, T>::type>
178 { /* DUMMY BODY */ };
179 }
180
181 template<class Alloc>
182 struct allocator_traits
183 {
184 using allocator_type = Alloc;
185
186 using value_type = typename Alloc::value_type;
187 using pointer = typename aux::get_pointer<Alloc>::type;
188 using const_pointer = typename aux::get_const_pointer<Alloc, pointer>::type;
189 // TODO: fix void pointer typedefs
190 /* using void_pointer = typename aux::get_void_pointer<Alloc, pointer>::type; */
191 /* using const_void_pointer = typename aux::get_const_void_pointer<Alloc, pointer>::type; */
192 using void_pointer = void*;
193 using const_void_pointer = const void*;
194 using difference_type = typename aux::get_difference_type<Alloc, pointer>::type;
195 using size_type = typename aux::get_size_type<Alloc, difference_type>::type;
196
197 using propagate_on_container_copy_assignment = typename aux::get_copy_propagate<Alloc>::type;
198 using propagate_on_container_move_assignment = typename aux::get_move_propagate<Alloc>::type;
199 using propagate_on_container_swap = typename aux::get_swap_propagate<Alloc>::type;
200 using is_always_equal = typename aux::get_always_equal<Alloc>::type;
201
202 template<class T>
203 using rebind_alloc = typename aux::get_rebind_args<Alloc, T>;
204
205 template<class T>
206 using rebind_traits = allocator_traits<rebind_alloc<T>>;
207
208 static pointer allocate(Alloc& alloc, size_type n)
209 {
210 return alloc.allocate(n);
211 }
212
213 static pointer allocate(Alloc& alloc, size_type n, const_void_pointer hint)
214 { // TODO: this when it's well formed, otherwise alloc.allocate(n)
215 return alloc.allocate(n, hint);
216 }
217
218 static void deallocate(Alloc& alloc, pointer ptr, size_type n)
219 {
220 alloc.deallocate(ptr, n);
221 }
222
223 template<class T, class... Args>
224 static void construct(Alloc& alloc, T* ptr, Args&&... args)
225 {
226 // TODO: implement
227 }
228
229 template<class T>
230 static void destroy(Alloc& alloc, T* ptr)
231 {
232 // TODO: implement
233 }
234
235 static size_type max_size(const Alloc& alloc) noexcept
236 {
237 // TODO: implement
238 return 0;
239 }
240
241 static Alloc select_on_container_copy_construction(const Alloc& alloc)
242 {
243 // TODO: implement
244 return Alloc{};
245 }
246 };
247
248 /**
249 * 20.7.9, the default allocator
250 */
251
252 template<class T>
253 class allocator;
254
255 template<>
256 class allocator<void>
257 {
258 public:
259 using pointer = void*;
260 using const_pointer = const void*;
261 using value_type = void;
262
263 template<class U>
264 struct rebind
265 {
266 using other = allocator<U>;
267 };
268 };
269
270 template<class T>
271 T* addressof(T& x) noexcept;
272
273 template<class T>
274 class allocator
275 {
276 public:
277 using size_type = size_t;
278 using difference_type = ptrdiff_t;
279 using pointer = T*;
280 using const_pointer = const T*;
281 using reference = T&;
282 using const_reference = const T&;
283 using value_type = T;
284
285 template<class U>
286 struct rebind
287 {
288 using other = allocator<U>;
289 };
290
291 using propagate_on_container_move_assignment = true_type;
292 using is_always_equal = true_type;
293
294 allocator() noexcept = default;
295
296 allocator(const allocator&) noexcept = default;
297
298 template<class U>
299 allocator(const allocator<U>&) noexcept
300 {
301 // TODO: implement
302 }
303
304 ~allocator() = default;
305
306 pointer address(reference x) const noexcept
307 {
308 return addressof(x);
309 }
310
311 const_pointer address(const_reference x) const noexcept
312 {
313 return addressof(x);
314 }
315
316 pointer allocate(size_type n, allocator<void>::const_pointer hint = 0)
317 {
318 /**
319 * Note: The usage of hint is unspecified.
320 * TODO: Check HelenOS hint allocation capabilities.
321 * TODO: assert that n < max_size()
322 */
323 return static_cast<pointer>(::operator new(n * sizeof(value_type)));
324 }
325
326 void deallocate(pointer ptr, size_type n)
327 {
328 ::operator delete(ptr, n);
329 }
330
331 size_type max_size() const noexcept
332 { // TODO: implement, max argument to allocate
333 return 0xFFFFFFFF;
334 }
335
336 template<class U, class... Args>
337 void construct(U* ptr, Args&&... args)
338 {
339 ::new((void*)ptr) U(forward<Args>(args)...);
340 }
341
342 template<class U>
343 void destroy(U* ptr)
344 {
345 ptr->~U();
346 }
347 };
348
349 template<class T1, class T2>
350 bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
351 {
352 return true;
353 }
354
355 template<class T1, class T2>
356 bool operator!=(const allocator<T1>&, const allocator<T2>&) noexcept
357 {
358 return false;
359 }
360
361 /**
362 * 20.7.10, raw storage iterator:
363 */
364
365 // TODO: implement
366
367 /**
368 * 20.7.11, temporary buffers:
369 */
370
371 // TODO: implement
372
373 /**
374 * 20.7.12, specialized algorithms:
375 */
376
377 template<class T>
378 T* addressof(T& x) noexcept
379 {
380 return reinterpret_cast<T*>(
381 &const_cast<char&>(
382 reinterpret_cast<const volatile char&>(x)
383 ));
384 }
385
386 template<class Iterator>
387 struct iterator_traits;
388
389 template<class InputIterator, class ForwardIterator>
390 ForwardIterator unitialized_copy(
391 InputIterator first, InputIterator last,
392 ForwardIterator result
393 )
394 {
395 for (; first != last; ++first, ++result)
396 ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first);
397
398 return result;
399 }
400
401 template<class InputIterator, class Size, class ForwardIterator>
402 ForwardIterator unitialized_copy_n(
403 InputIterator first, Size n, ForwardIterator result
404 )
405 {
406 for (; n > 0; ++first, --n, ++result)
407 ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first);
408
409 return result;
410 }
411
412 template<class ForwardIterator, class T>
413 void unitialized_fill(
414 ForwardIterator first, ForwardIterator last, const T& x
415 )
416 {
417 for (; first != last; ++first)
418 ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x);
419 }
420
421 template<class ForwardIterator, class Size, class T>
422 ForwardIterator unitialized_fill_n(
423 ForwardIterator first, Size n, const T& x
424 )
425 {
426 for (; n > 0; ++first, --n)
427 ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x);
428
429 return first;
430 }
431
432 /**
433 * 20.8, smart pointers:
434 */
435
436 template<class T>
437 struct default_delete
438 {
439 default_delete() noexcept = default;
440
441 template<class U, class = enable_if_t<is_convertible_v<U*, T*>, void>>
442 default_delete(const default_delete<U>&) noexcept
443 { /* DUMMY BODY */ }
444
445 template<class U>
446 void operator()(U* ptr)
447 {
448 delete ptr;
449 }
450 };
451
452 template<class T>
453 struct default_delete<T[]>
454 {
455 default_delete() noexcept = default;
456
457 template<class U, class = enable_if_t<is_convertible_v<U(*)[], T(*)[]>, void>>
458 default_delete(const default_delete<U[]>&) noexcept
459 { /* DUMMY BODY */ }
460
461 template<class U, class = enable_if_t<is_convertible_v<U(*)[], T(*)[]>, void>>
462 void operator()(U* ptr)
463 {
464 delete[] ptr;
465 }
466 };
467
468 template<class T, class D = default_delete<T>>
469 class unique_ptr;
470
471 namespace aux
472 {
473 template<class P, class D, class = void>
474 struct get_unique_pointer: type_is<typename P::element_type*>
475 { /* DUMMY BODY */ };
476
477 template<class P, class D>
478 struct get_unique_pointer<P, D, void_t<typename remove_reference_t<D>::pointer>>
479 : type_is<typename remove_reference_t<D>::pointer>
480 { /* DUMMY BODY */ };
481 }
482
483 template<class T, class D>
484 class unique_ptr
485 {
486 public:
487 using element_type = T;
488 using deleter_type = D;
489 using pointer = typename aux::get_unique_pointer<unique_ptr<T, D>, D>::type;
490
491 /**
492 * 20.8.1.2.1, constructors:
493 */
494
495 constexpr unique_ptr() noexcept
496 : ptr_{}, deleter_{}
497 { /* DUMMY BODY */ }
498
499 explicit unique_ptr(pointer ptr) noexcept
500 : ptr_{ptr}, deleter_{}
501 { /* DUMMY BODY */ }
502
503 unique_ptr(pointer ptr, /* TODO */ int d) noexcept;
504
505 unique_ptr(pointer ptr, /* TODO */ char d) noexcept;
506
507 unique_ptr(unique_ptr&& other)
508 : ptr_{move(other.ptr_)}, deleter_{forward<deleter_type>(other.deleter_)}
509 {
510 other.ptr_ = nullptr;
511 }
512
513 constexpr unique_ptr(nullptr_t)
514 : unique_ptr{}
515 { /* DUMMY BODY */ }
516
517 template<
518 class U, class E,
519 class = enable_if_t<
520 is_convertible_v<
521 typename unique_ptr<U, E>::pointer,
522 pointer
523 >, void
524 >
525 >
526 unique_ptr(unique_ptr<U, E>&& other) noexcept
527 : ptr_{move(other.ptr_)}, deleter_{forward<D>(other.deleter_)}
528 {
529 other.ptr_ = nullptr;
530 }
531
532 /**
533 * 20.8.1.2.2, destructor:
534 */
535
536 ~unique_ptr()
537 {
538 if (ptr_)
539 deleter_(ptr_);
540 }
541
542 /**
543 * 20.8.1.2.3, assignment:
544 */
545
546 unique_ptr& operator=(unique_ptr&& rhs) noexcept
547 {
548 reset(rhs.release());
549 deleter_ = forward<deleter_type>(rhs.get_deleter());
550
551 return *this;
552 }
553
554 template<
555 class U, class E,
556 class = enable_if_t<
557 is_convertible_v<
558 typename unique_ptr<U, E>::pointer,
559 pointer
560 > && !is_array_v<U>, void
561 >
562 >
563 unique_ptr& operator=(unique_ptr<U, E>&& rhs) noexcept
564 {
565 reset(rhs.release());
566 deleter_ = forward<E>(rhs.get_deleter());
567
568 return *this;
569 }
570
571 unique_ptr& operator=(nullptr_t) noexcept
572 {
573 reset();
574
575 return *this;
576 }
577
578 /**
579 * 20.8.1.2.4, observers:
580 */
581
582 add_lvalue_reference_t<element_type> operator*() const
583 {
584 return *ptr_;
585 }
586
587 pointer operator->() const noexcept
588 {
589 return ptr_;
590 }
591
592 pointer get() const noexcept
593 {
594 return ptr_;
595 }
596
597 deleter_type& get_deleter() noexcept
598 {
599 return deleter_;
600 }
601
602 const deleter_type& get_deleter() const noexcept
603 {
604 return deleter_;
605 }
606
607 explicit operator bool() const noexcept
608 {
609 return ptr_ != nullptr;
610 }
611
612 /**
613 * 20.8.1.2.5, modifiers:
614 */
615
616 pointer release() noexcept
617 {
618 auto ret = ptr_;
619 ptr_ = nullptr;
620
621 return ret;
622 }
623
624 void reset(pointer ptr = pointer{}) noexcept
625 {
626 /**
627 * Note: Order is significant, deleter may delete
628 * *this.
629 */
630 auto old = ptr_;
631 ptr_ = ptr;
632
633 if (old)
634 deleter_(old);
635 }
636
637 void swap(unique_ptr& other) noexcept
638 {
639 std::swap(ptr_, other.ptr_);
640 std::swap(deleter_, other.deleter_);
641 }
642
643 unique_ptr(const unique_ptr&) = delete;
644 unique_ptr& operator=(const unique_ptr&) = delete;
645
646 private:
647 pointer ptr_;
648 deleter_type deleter_;
649 };
650
651 namespace aux
652 {
653 template<class From, class To>
654 struct is_convertible_array: is_convertible<From(*)[], To(*)[]>
655 { /* DUMMY BODY */ };
656
657 template<class From, class To>
658 inline constexpr bool is_convertible_array_v = is_convertible_array<From, To>::value;
659
660 template<class T, class D, class U, class E>
661 struct compatible_ptrs: integral_constant<
662 bool,
663 is_array_v<U> && is_same_v<
664 typename unique_ptr<T, D>::pointer,
665 typename unique_ptr<T, D>::element_type*
666 > && is_same_v<
667 typename unique_ptr<U, E>::pointer,
668 typename unique_ptr<U, E>::element_type*
669 > && is_convertible_array_v<
670 typename unique_ptr<T, D>::element_type,
671 typename unique_ptr<U, E>::element_type
672 > && ((is_reference_v<D> && is_same_v<D, E>) ||
673 (!is_reference_v<D> && is_convertible_v<E, D>))
674 >
675 { /* DUMMY BODY */ };
676
677 template<class T, class D, class U, class E>
678 inline constexpr bool compatible_ptrs_v = compatible_ptrs<T, D, U, E>::value;
679 }
680
681 template<class T, class D>
682 class unique_ptr<T[], D>
683 {
684 public:
685 using element_type = T;
686 using deleter_type = D;
687 using pointer = typename aux::get_unique_pointer<unique_ptr<T[], D>, D>::type;
688
689 /**
690 * 20.8.1.3.1, constructors:
691 */
692
693 constexpr unique_ptr() noexcept
694 : ptr_{}, deleter_{}
695 { /* DUMMY BODY */ }
696
697 template<
698 class U,
699 class = enable_if_t<
700 is_same_v<U, T> || aux::is_convertible_array_v<U, T>, void
701 >
702 >
703 explicit unique_ptr(U ptr) noexcept
704 : ptr_{ptr}, deleter_{}
705 { /* DUMMY BODY */ }
706
707 template<
708 class U, class E,
709 class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
710 >
711 unique_ptr(U ptr, /* TODO */ int d) noexcept;
712
713 template<
714 class U, class E,
715 class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
716 >
717 unique_ptr(U ptr, /* TODO */ char d) noexcept;
718
719 unique_ptr(unique_ptr&& other) noexcept
720 : ptr_{move(other.ptr_)}, deleter_{forward<deleter_type>(other.deleter_)}
721 {
722 other.ptr_ = nullptr;
723 }
724
725 template<
726 class U, class E,
727 class = enable_if_t<
728 is_same_v<U, pointer> ||
729 (is_same_v<pointer, element_type*> && is_pointer_v<U> &&
730 aux::is_convertible_array_v<remove_pointer_t<U>, element_type>),
731 void
732 >
733 >
734 unique_ptr(unique_ptr<U, E>&& other) noexcept
735 : ptr_{move(other.ptr_)}, deleter_{forward<D>(other.deleter_)}
736 {
737 other.ptr_ = nullptr;
738 }
739
740 constexpr unique_ptr(nullptr_t) noexcept
741 : unique_ptr{}
742 { /* DUMMY BODY */ }
743
744 ~unique_ptr()
745 {
746 if (ptr_)
747 deleter_(ptr_);
748 }
749
750 /**
751 * 20.8.1.3.2, assignment:
752 */
753
754 unique_ptr& operator=(unique_ptr&& rhs) noexcept
755 {
756 reset(rhs.release());
757 deleter_ = forward<deleter_type>(rhs.get_deleter());
758
759 return *this;
760 }
761
762 template<
763 class U, class E,
764 class = enable_if_t<aux::compatible_ptrs_v<T, D, U, E>, void>
765 >
766 unique_ptr& operator=(unique_ptr<U, E>&& rhs) noexcept
767 {
768 reset(rhs.release());
769 deleter_ = forward<E>(rhs.get_deleter());
770
771 return *this;
772 }
773
774 unique_ptr& operator=(nullptr_t) noexcept
775 {
776 reset();
777
778 return *this;
779 }
780
781 /**
782 * 20.8.1.3.3, observers:
783 */
784
785 element_type& operator[](size_t idx) const
786 {
787 return ptr_[idx];
788 }
789
790 pointer get() const noexcept
791 {
792 return ptr_;
793 }
794
795 deleter_type& get_deleter() noexcept
796 {
797 return deleter_;
798 }
799
800 const deleter_type& get_deleter() const noexcept
801 {
802 return deleter_;
803 }
804
805 explicit operator bool() const noexcept
806 {
807 return ptr_ != nullptr;
808 }
809
810 /**
811 * 20.8.1.3.4, modifiers:
812 */
813
814 pointer release() noexcept
815 {
816 auto ret = ptr_;
817 ptr_ = nullptr;
818
819 return ret;
820 }
821
822 template<
823 class U,
824 class = enable_if_t<
825 is_same_v<U, pointer> ||
826 (is_same_v<pointer, element_type*> && is_pointer_v<U> &&
827 aux::is_convertible_array_v<remove_pointer_t<U>, element_type>),
828 void
829 >
830 >
831 void reset(U ptr) noexcept
832 {
833 /**
834 * Note: Order is significant, deleter may delete
835 * *this.
836 */
837 auto old = ptr_;
838 ptr_ = ptr;
839
840 if (old)
841 deleter_(old);
842 }
843
844 void reset(nullptr_t = nullptr) noexcept
845 {
846 reset(pointer{});
847 }
848
849 void swap(unique_ptr& other) noexcept
850 {
851 std::swap(ptr_, other.ptr_);
852 std::swap(deleter_, other.deleter_);
853 }
854
855 unique_ptr(const unique_ptr&) = delete;
856 unique_ptr& operator=(const unique_ptr&) = delete;
857
858 private:
859 pointer ptr_;
860 deleter_type deleter_;
861 };
862
863 namespace aux
864 {
865 template<class T>
866 struct is_unbound_array: false_type
867 { /* DUMMY BODY */ };
868
869 template<class T>
870 struct is_unbound_array<T[]>: true_type
871 { /* DUMMY BODY */ };
872
873 template<class T>
874 struct is_bound_array: false_type
875 { /* DUMMY BODY */ };
876
877 template<class T, size_t N>
878 struct is_bound_array<T[N]>: true_type
879 { /* DUMMY BODY */ };
880 }
881
882 template<
883 class T, class... Args,
884 class = enable_if_t<!is_array_v<T>, void>
885 >
886 unique_ptr<T> make_unique(Args&&... args)
887 {
888 return unique_ptr<T>(new T(forward<Args>(args)...));
889 }
890
891 template<
892 class T, class = enable_if_t<aux::is_unbound_array<T>::value, void>
893 >
894 unique_ptr<T> make_unique(size_t n)
895 {
896 return unique_ptr<T>(new remove_extent_t<T>[n]());
897 }
898
899 template<
900 class T, class... Args,
901 class = enable_if_t<aux::is_bound_array<T>::value, void>
902 >
903 void make_unique(Args&&...) = delete;
904
905 template<class T, class D>
906 void swap(unique_ptr<T, D>& lhs, unique_ptr<T, D>& rhs) noexcept
907 {
908 lhs.swap(rhs);
909 }
910
911 template<class T1, class D1, class T2, class D2>
912 bool operator==(const unique_ptr<T1, D1>& lhs,
913 const unique_ptr<T2, D2>& rhs)
914 {
915 return lhs.get() == rhs.get();
916 }
917
918 template<class T1, class D1, class T2, class D2>
919 bool operator!=(const unique_ptr<T1, D1>& lhs,
920 const unique_ptr<T2, D2>& rhs)
921 {
922 return lhs.get() != rhs.get();
923 }
924
925 template<class T1, class D1, class T2, class D2>
926 bool operator<(const unique_ptr<T1, D1>& lhs,
927 const unique_ptr<T2, D2>& rhs)
928 {
929 return lhs.get() < rhs.get();
930 }
931
932 template<class T1, class D1, class T2, class D2>
933 bool operator<=(const unique_ptr<T1, D1>& lhs,
934 const unique_ptr<T2, D2>& rhs)
935 {
936 return !(rhs < lhs);
937 }
938
939 template<class T1, class D1, class T2, class D2>
940 bool operator>(const unique_ptr<T1, D1>& lhs,
941 const unique_ptr<T2, D2>& rhs)
942 {
943 return rhs < lhs;
944 }
945
946 template<class T1, class D1, class T2, class D2>
947 bool operator>=(const unique_ptr<T1, D1>& lhs,
948 const unique_ptr<T2, D2>& rhs)
949 {
950 return !(lhs < rhs);
951 }
952
953 template<class T, class D>
954 bool operator==(const unique_ptr<T, D>& ptr, nullptr_t) noexcept
955 {
956 return !ptr;
957 }
958
959 template<class T, class D>
960 bool operator==(nullptr_t, const unique_ptr<T, D>& ptr) noexcept
961 {
962 return !ptr;
963 }
964
965 template<class T, class D>
966 bool operator!=(const unique_ptr<T, D>& ptr, nullptr_t) noexcept
967 {
968 return static_cast<bool>(ptr);
969 }
970
971 template<class T, class D>
972 bool operator!=(nullptr_t, const unique_ptr<T, D>& ptr) noexcept
973 {
974 return static_cast<bool>(ptr);
975 }
976
977 template<class T, class D>
978 bool operator<(const unique_ptr<T, D>& ptr, nullptr_t)
979 {
980 return ptr.get() < nullptr;
981 }
982
983 template<class T, class D>
984 bool operator<(nullptr_t, const unique_ptr<T, D>& ptr)
985 {
986 return nullptr < ptr.get();
987 }
988
989 template<class T, class D>
990 bool operator<=(const unique_ptr<T, D>& ptr, nullptr_t)
991 {
992 return !(nullptr < ptr);
993 }
994
995 template<class T, class D>
996 bool operator<=(nullptr_t, const unique_ptr<T, D>& ptr)
997 {
998 return !(ptr < nullptr);
999 }
1000
1001 template<class T, class D>
1002 bool operator>(const unique_ptr<T, D>& ptr, nullptr_t)
1003 {
1004 return nullptr < ptr;
1005 }
1006
1007 template<class T, class D>
1008 bool operator>(nullptr_t, const unique_ptr<T, D>& ptr)
1009 {
1010 return ptr < nullptr;
1011 }
1012
1013 template<class T, class D>
1014 bool operator>=(const unique_ptr<T, D>& ptr, nullptr_t)
1015 {
1016 return !(ptr < nullptr);
1017 }
1018
1019 template<class T, class D>
1020 bool operator>=(nullptr_t, const unique_ptr<T, D>& ptr)
1021 {
1022 return !(nullptr < ptr);
1023 }
1024}
1025
1026#endif
Note: See TracBrowser for help on using the repository browser.