• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
testAssign(APtr & aptr,BPtr & 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>
checkDeleter(LHS & lhs,RHS & rhs,int LHSState,int RHSState)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>
NCConvertingDeleterNCConvertingDeleter49   NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
50 
operator ()NCConvertingDeleter51   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>
NCConvertingDeleterNCConvertingDeleter61   NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
62 
operator ()NCConvertingDeleter63   void operator()(T*) const {}
64 };
65 
66 struct NCGenericDeleter {
67   NCGenericDeleter() = default;
68   NCGenericDeleter(NCGenericDeleter const&) = delete;
69   NCGenericDeleter(NCGenericDeleter&&) = default;
70 
operator ()NCGenericDeleter71   void operator()(void*) const {}
72 };
73 
test_sfinae()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 
main()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 }
146