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