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

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

cpp: fixed typedefs in allocator_traits, finished type getters and implemented conditional calls in allocator_traits

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