move_convert.single.pass.cpp (7114B)
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 11 // <memory> 12 13 // unique_ptr 14 15 // Test unique_ptr converting move ctor 16 17 // NOTE: unique_ptr does not provide converting constructors in C++03 18 // UNSUPPORTED: c++98, c++03 19 20 #include <memory> 21 #include <type_traits> 22 #include <utility> 23 #include <cassert> 24 25 #include "test_macros.h" 26 #include "unique_ptr_test_helper.h" 27 28 // test converting move ctor. Should only require a MoveConstructible deleter, or if 29 // deleter is a reference, not even that. 30 // Explicit version 31 32 template <class LHS, class RHS> 33 void checkReferenceDeleter(LHS& lhs, RHS& rhs) { 34 typedef typename LHS::deleter_type NewDel; 35 static_assert(std::is_reference<NewDel>::value, ""); 36 rhs.get_deleter().set_state(42); 37 assert(rhs.get_deleter().state() == 42); 38 assert(lhs.get_deleter().state() == 42); 39 lhs.get_deleter().set_state(99); 40 assert(lhs.get_deleter().state() == 99); 41 assert(rhs.get_deleter().state() == 99); 42 } 43 44 template <class LHS, class RHS> 45 void checkDeleter(LHS& lhs, RHS& rhs, int LHSVal, int RHSVal) { 46 assert(lhs.get_deleter().state() == LHSVal); 47 assert(rhs.get_deleter().state() == RHSVal); 48 } 49 50 template <class LHS, class RHS> 51 void checkCtor(LHS& lhs, RHS& rhs, A* RHSVal) { 52 assert(lhs.get() == RHSVal); 53 assert(rhs.get() == nullptr); 54 assert(A::count == 1); 55 assert(B::count == 1); 56 } 57 58 void checkNoneAlive() { 59 assert(A::count == 0); 60 assert(B::count == 0); 61 } 62 63 template <class T> 64 struct NCConvertingDeleter { 65 NCConvertingDeleter() = default; 66 NCConvertingDeleter(NCConvertingDeleter const&) = delete; 67 NCConvertingDeleter(NCConvertingDeleter&&) = default; 68 69 template <class U> 70 NCConvertingDeleter(NCConvertingDeleter<U>&&) {} 71 72 void operator()(T*) const {} 73 }; 74 75 template <class T> 76 struct NCConvertingDeleter<T[]> { 77 NCConvertingDeleter() = default; 78 NCConvertingDeleter(NCConvertingDeleter const&) = delete; 79 NCConvertingDeleter(NCConvertingDeleter&&) = default; 80 81 template <class U> 82 NCConvertingDeleter(NCConvertingDeleter<U>&&) {} 83 84 void operator()(T*) const {} 85 }; 86 87 struct NCGenericDeleter { 88 NCGenericDeleter() = default; 89 NCGenericDeleter(NCGenericDeleter const&) = delete; 90 NCGenericDeleter(NCGenericDeleter&&) = default; 91 92 void operator()(void*) const {} 93 }; 94 95 void test_sfinae() { 96 using DA = NCConvertingDeleter<A>; // non-copyable deleters 97 using DB = NCConvertingDeleter<B>; 98 using UA = std::unique_ptr<A>; 99 using UB = std::unique_ptr<B>; 100 using UAD = std::unique_ptr<A, DA>; 101 using UBD = std::unique_ptr<B, DB>; 102 { // cannot move from an lvalue 103 static_assert(std::is_constructible<UA, UB&&>::value, ""); 104 static_assert(!std::is_constructible<UA, UB&>::value, ""); 105 static_assert(!std::is_constructible<UA, const UB&>::value, ""); 106 } 107 { // cannot move if the deleter-types cannot convert 108 static_assert(std::is_constructible<UAD, UBD&&>::value, ""); 109 static_assert(!std::is_constructible<UAD, UB&&>::value, ""); 110 static_assert(!std::is_constructible<UA, UBD&&>::value, ""); 111 } 112 { // cannot move-convert with reference deleters of different types 113 using UA1 = std::unique_ptr<A, DA&>; 114 using UB1 = std::unique_ptr<B, DB&>; 115 static_assert(!std::is_constructible<UA1, UB1&&>::value, ""); 116 } 117 { // cannot move-convert with reference deleters of different types 118 using UA1 = std::unique_ptr<A, const DA&>; 119 using UB1 = std::unique_ptr<B, const DB&>; 120 static_assert(!std::is_constructible<UA1, UB1&&>::value, ""); 121 } 122 { // cannot move-convert from unique_ptr<Array[]> 123 using UA1 = std::unique_ptr<A>; 124 using UA2 = std::unique_ptr<A[]>; 125 using UB1 = std::unique_ptr<B[]>; 126 static_assert(!std::is_constructible<UA1, UA2&&>::value, ""); 127 static_assert(!std::is_constructible<UA1, UB1&&>::value, ""); 128 } 129 { // cannot move-convert from unique_ptr<Array[]> 130 using UA1 = std::unique_ptr<A, NCGenericDeleter>; 131 using UA2 = std::unique_ptr<A[], NCGenericDeleter>; 132 using UB1 = std::unique_ptr<B[], NCGenericDeleter>; 133 static_assert(!std::is_constructible<UA1, UA2&&>::value, ""); 134 static_assert(!std::is_constructible<UA1, UB1&&>::value, ""); 135 } 136 } 137 138 void test_noexcept() { 139 { 140 typedef std::unique_ptr<A> APtr; 141 typedef std::unique_ptr<B> BPtr; 142 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, ""); 143 } 144 { 145 typedef std::unique_ptr<A, Deleter<A> > APtr; 146 typedef std::unique_ptr<B, Deleter<B> > BPtr; 147 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, ""); 148 } 149 { 150 typedef std::unique_ptr<A, NCDeleter<A>&> APtr; 151 typedef std::unique_ptr<B, NCDeleter<A>&> BPtr; 152 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, ""); 153 } 154 { 155 typedef std::unique_ptr<A, const NCConstDeleter<A>&> APtr; 156 typedef std::unique_ptr<B, const NCConstDeleter<A>&> BPtr; 157 static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, ""); 158 } 159 } 160 161 int main() { 162 { 163 test_sfinae(); 164 test_noexcept(); 165 } 166 { 167 typedef std::unique_ptr<A> APtr; 168 typedef std::unique_ptr<B> BPtr; 169 { // explicit 170 BPtr b(new B); 171 A* p = b.get(); 172 APtr a(std::move(b)); 173 checkCtor(a, b, p); 174 } 175 checkNoneAlive(); 176 { // implicit 177 BPtr b(new B); 178 A* p = b.get(); 179 APtr a = std::move(b); 180 checkCtor(a, b, p); 181 } 182 checkNoneAlive(); 183 } 184 { // test with moveable deleters 185 typedef std::unique_ptr<A, Deleter<A> > APtr; 186 typedef std::unique_ptr<B, Deleter<B> > BPtr; 187 { 188 Deleter<B> del(5); 189 BPtr b(new B, std::move(del)); 190 A* p = b.get(); 191 APtr a(std::move(b)); 192 checkCtor(a, b, p); 193 checkDeleter(a, b, 5, 0); 194 } 195 checkNoneAlive(); 196 { 197 Deleter<B> del(5); 198 BPtr b(new B, std::move(del)); 199 A* p = b.get(); 200 APtr a = std::move(b); 201 checkCtor(a, b, p); 202 checkDeleter(a, b, 5, 0); 203 } 204 checkNoneAlive(); 205 } 206 { // test with reference deleters 207 typedef std::unique_ptr<A, NCDeleter<A>&> APtr; 208 typedef std::unique_ptr<B, NCDeleter<A>&> BPtr; 209 NCDeleter<A> del(5); 210 { 211 BPtr b(new B, del); 212 A* p = b.get(); 213 APtr a(std::move(b)); 214 checkCtor(a, b, p); 215 checkReferenceDeleter(a, b); 216 } 217 checkNoneAlive(); 218 { 219 BPtr b(new B, del); 220 A* p = b.get(); 221 APtr a = std::move(b); 222 checkCtor(a, b, p); 223 checkReferenceDeleter(a, b); 224 } 225 checkNoneAlive(); 226 } 227 { 228 typedef std::unique_ptr<A, CDeleter<A> > APtr; 229 typedef std::unique_ptr<B, CDeleter<B>&> BPtr; 230 CDeleter<B> del(5); 231 { 232 BPtr b(new B, del); 233 A* p = b.get(); 234 APtr a(std::move(b)); 235 checkCtor(a, b, p); 236 checkDeleter(a, b, 5, 5); 237 } 238 checkNoneAlive(); 239 { 240 BPtr b(new B, del); 241 A* p = b.get(); 242 APtr a = std::move(b); 243 checkCtor(a, b, p); 244 checkDeleter(a, b, 5, 5); 245 } 246 checkNoneAlive(); 247 } 248 }