1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // <memory> 10 11 // unique_ptr 12 13 // Test unique_ptr move ctor 14 15 #include <memory> 16 #include <utility> 17 #include <cassert> 18 19 #include "test_macros.h" 20 #include "unique_ptr_test_helper.h" 21 22 //============================================================================= 23 // TESTING unique_ptr(unique_ptr&&) 24 // 25 // Concerns 26 // 1 The moved from pointer is empty and the new pointer stores the old value. 27 // 2 The only requirement on the deleter is that it is MoveConstructible 28 // or a reference. 29 // 3 The constructor works for explicitly moved values (i.e. std::move(x)) 30 // 4 The constructor works for true temporaries (e.g. a return value) 31 // 32 // Plan 33 // 1 Explicitly construct unique_ptr<T, D> for various deleter types 'D'. 34 // check that the value and deleter have been properly moved. (C-1,2,3) 35 // 36 // 2 Use the expression 'sink(source())' to move construct a unique_ptr<T, D> 37 // from a temporary. 'source' should return the unique_ptr by value and 38 // 'sink' should accept the unique_ptr by value. (C-1,2,4) 39 40 template <class VT> 41 std::unique_ptr<VT> source1() { 42 return std::unique_ptr<VT>(newValue<VT>(1)); 43 } 44 45 template <class VT> 46 std::unique_ptr<VT, Deleter<VT> > source2() { 47 return std::unique_ptr<VT, Deleter<VT> >(newValue<VT>(1), Deleter<VT>(5)); 48 } 49 50 template <class VT> 51 std::unique_ptr<VT, NCDeleter<VT>&> source3() { 52 static NCDeleter<VT> d(5); 53 return std::unique_ptr<VT, NCDeleter<VT>&>(newValue<VT>(1), d); 54 } 55 56 template <class VT> 57 void sink1(std::unique_ptr<VT> p) { 58 assert(p.get() != nullptr); 59 } 60 61 template <class VT> 62 void sink2(std::unique_ptr<VT, Deleter<VT> > p) { 63 assert(p.get() != nullptr); 64 assert(p.get_deleter().state() == 5); 65 } 66 67 template <class VT> 68 void sink3(std::unique_ptr<VT, NCDeleter<VT>&> p) { 69 assert(p.get() != nullptr); 70 assert(p.get_deleter().state() == 5); 71 assert(&p.get_deleter() == &source3<VT>().get_deleter()); 72 } 73 74 template <class ValueT> 75 void test_sfinae() { 76 typedef std::unique_ptr<ValueT> U; 77 { // Ensure unique_ptr is non-copyable 78 static_assert((!std::is_constructible<U, U const&>::value), ""); 79 static_assert((!std::is_constructible<U, U&>::value), ""); 80 } 81 } 82 83 template <bool IsArray> 84 void test_basic() { 85 typedef typename std::conditional<!IsArray, A, A[]>::type VT; 86 const int expect_alive = IsArray ? 5 : 1; 87 { 88 typedef std::unique_ptr<VT> APtr; 89 APtr s(newValue<VT>(expect_alive)); 90 A* p = s.get(); 91 APtr s2 = std::move(s); 92 assert(s2.get() == p); 93 assert(s.get() == 0); 94 assert(A::count == expect_alive); 95 } 96 assert(A::count == 0); 97 { 98 typedef Deleter<VT> MoveDel; 99 typedef std::unique_ptr<VT, MoveDel> APtr; 100 MoveDel d(5); 101 APtr s(newValue<VT>(expect_alive), std::move(d)); 102 assert(d.state() == 0); 103 assert(s.get_deleter().state() == 5); 104 A* p = s.get(); 105 APtr s2 = std::move(s); 106 assert(s2.get() == p); 107 assert(s.get() == 0); 108 assert(A::count == expect_alive); 109 assert(s2.get_deleter().state() == 5); 110 assert(s.get_deleter().state() == 0); 111 } 112 assert(A::count == 0); 113 { 114 typedef NCDeleter<VT> NonCopyDel; 115 typedef std::unique_ptr<VT, NonCopyDel&> APtr; 116 117 NonCopyDel d; 118 APtr s(newValue<VT>(expect_alive), d); 119 A* p = s.get(); 120 APtr s2 = std::move(s); 121 assert(s2.get() == p); 122 assert(s.get() == 0); 123 assert(A::count == expect_alive); 124 d.set_state(6); 125 assert(s2.get_deleter().state() == d.state()); 126 assert(s.get_deleter().state() == d.state()); 127 } 128 assert(A::count == 0); 129 { 130 sink1<VT>(source1<VT>()); 131 assert(A::count == 0); 132 sink2<VT>(source2<VT>()); 133 assert(A::count == 0); 134 sink3<VT>(source3<VT>()); 135 assert(A::count == 0); 136 } 137 assert(A::count == 0); 138 } 139 140 template <class VT> 141 void test_noexcept() { 142 #if TEST_STD_VER >= 11 143 { 144 typedef std::unique_ptr<VT> U; 145 static_assert(std::is_nothrow_move_constructible<U>::value, ""); 146 } 147 { 148 typedef std::unique_ptr<VT, Deleter<VT> > U; 149 static_assert(std::is_nothrow_move_constructible<U>::value, ""); 150 } 151 { 152 typedef std::unique_ptr<VT, NCDeleter<VT> &> U; 153 static_assert(std::is_nothrow_move_constructible<U>::value, ""); 154 } 155 { 156 typedef std::unique_ptr<VT, const NCConstDeleter<VT> &> U; 157 static_assert(std::is_nothrow_move_constructible<U>::value, ""); 158 } 159 #endif 160 } 161 162 int main(int, char**) { 163 { 164 test_basic</*IsArray*/ false>(); 165 test_sfinae<int>(); 166 test_noexcept<int>(); 167 } 168 { 169 test_basic</*IsArray*/ true>(); 170 test_sfinae<int[]>(); 171 test_noexcept<int[]>(); 172 } 173 174 return 0; 175 } 176