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