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

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

cpp: moved type getters for allocator and pointer traits to a separate header, fully implemented pointer_traits and added pointer_traits tests

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