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