move_convert.single.pass.cpp (4425B)
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 // UNSUPPORTED: c++98, c++03 11 12 // <memory> 13 14 // unique_ptr 15 16 // Test unique_ptr converting move assignment 17 18 #include <memory> 19 #include <utility> 20 #include <cassert> 21 22 #include "deleter_types.h" 23 #include "unique_ptr_test_helper.h" 24 25 template <class APtr, class BPtr> 26 void testAssign(APtr& aptr, BPtr& bptr) { 27 A* p = bptr.get(); 28 assert(A::count == 2); 29 aptr = std::move(bptr); 30 assert(aptr.get() == p); 31 assert(bptr.get() == 0); 32 assert(A::count == 1); 33 assert(B::count == 1); 34 } 35 36 template <class LHS, class RHS> 37 void checkDeleter(LHS& lhs, RHS& rhs, int LHSState, int RHSState) { 38 assert(lhs.get_deleter().state() == LHSState); 39 assert(rhs.get_deleter().state() == RHSState); 40 } 41 42 template <class T> 43 struct NCConvertingDeleter { 44 NCConvertingDeleter() = default; 45 NCConvertingDeleter(NCConvertingDeleter const&) = delete; 46 NCConvertingDeleter(NCConvertingDeleter&&) = default; 47 48 template <class U> 49 NCConvertingDeleter(NCConvertingDeleter<U>&&) {} 50 51 void operator()(T*) const {} 52 }; 53 54 template <class T> 55 struct NCConvertingDeleter<T[]> { 56 NCConvertingDeleter() = default; 57 NCConvertingDeleter(NCConvertingDeleter const&) = delete; 58 NCConvertingDeleter(NCConvertingDeleter&&) = default; 59 60 template <class U> 61 NCConvertingDeleter(NCConvertingDeleter<U>&&) {} 62 63 void operator()(T*) const {} 64 }; 65 66 struct NCGenericDeleter { 67 NCGenericDeleter() = default; 68 NCGenericDeleter(NCGenericDeleter const&) = delete; 69 NCGenericDeleter(NCGenericDeleter&&) = default; 70 71 void operator()(void*) const {} 72 }; 73 74 void test_sfinae() { 75 using DA = NCConvertingDeleter<A>; // non-copyable deleters 76 using DB = NCConvertingDeleter<B>; 77 using UA = std::unique_ptr<A>; 78 using UB = std::unique_ptr<B>; 79 using UAD = std::unique_ptr<A, DA>; 80 using UBD = std::unique_ptr<B, DB>; 81 { // cannot move from an lvalue 82 static_assert(std::is_assignable<UA, UB&&>::value, ""); 83 static_assert(!std::is_assignable<UA, UB&>::value, ""); 84 static_assert(!std::is_assignable<UA, const UB&>::value, ""); 85 } 86 { // cannot move if the deleter-types cannot convert 87 static_assert(std::is_assignable<UAD, UBD&&>::value, ""); 88 static_assert(!std::is_assignable<UAD, UB&&>::value, ""); 89 static_assert(!std::is_assignable<UA, UBD&&>::value, ""); 90 } 91 { // cannot move-convert with reference deleters of different types 92 using UA1 = std::unique_ptr<A, DA&>; 93 using UB1 = std::unique_ptr<B, DB&>; 94 static_assert(!std::is_assignable<UA1, UB1&&>::value, ""); 95 } 96 { // cannot move-convert with reference deleters of different types 97 using UA1 = std::unique_ptr<A, const DA&>; 98 using UB1 = std::unique_ptr<B, const DB&>; 99 static_assert(!std::is_assignable<UA1, UB1&&>::value, ""); 100 } 101 { // cannot move-convert from unique_ptr<Array[]> 102 using UA1 = std::unique_ptr<A>; 103 using UA2 = std::unique_ptr<A[]>; 104 using UB1 = std::unique_ptr<B[]>; 105 static_assert(!std::is_assignable<UA1, UA2&&>::value, ""); 106 static_assert(!std::is_assignable<UA1, UB1&&>::value, ""); 107 } 108 { // cannot move-convert from unique_ptr<Array[]> 109 using UA1 = std::unique_ptr<A, NCGenericDeleter>; 110 using UA2 = std::unique_ptr<A[], NCGenericDeleter>; 111 using UB1 = std::unique_ptr<B[], NCGenericDeleter>; 112 static_assert(!std::is_assignable<UA1, UA2&&>::value, ""); 113 static_assert(!std::is_assignable<UA1, UB1&&>::value, ""); 114 } 115 } 116 117 int main() { 118 test_sfinae(); 119 { 120 std::unique_ptr<B> bptr(new B); 121 std::unique_ptr<A> aptr(new A); 122 testAssign(aptr, bptr); 123 } 124 assert(A::count == 0); 125 assert(B::count == 0); 126 { 127 Deleter<B> del(42); 128 std::unique_ptr<B, Deleter<B> > bptr(new B, std::move(del)); 129 std::unique_ptr<A, Deleter<A> > aptr(new A); 130 testAssign(aptr, bptr); 131 checkDeleter(aptr, bptr, 42, 0); 132 } 133 assert(A::count == 0); 134 assert(B::count == 0); 135 { 136 CDeleter<A> adel(6); 137 CDeleter<B> bdel(42); 138 std::unique_ptr<B, CDeleter<B>&> bptr(new B, bdel); 139 std::unique_ptr<A, CDeleter<A>&> aptr(new A, adel); 140 testAssign(aptr, bptr); 141 checkDeleter(aptr, bptr, 42, 42); 142 } 143 assert(A::count == 0); 144 assert(B::count == 0); 145 }