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 // <memory>
11 
12 // unique_ptr
13 
14 // Test unique_ptr converting move ctor
15 
16 #include <memory>
17 #include <utility>
18 #include <cassert>
19 
20 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
21 //    deleter is a reference, not even that.
22 // Implicit version
23 
24 struct A
25 {
26     static int count;
AA27     A() {++count;}
AA28     A(const A&) {++count;}
~AA29     virtual ~A() {--count;}
30 };
31 
32 int A::count = 0;
33 
34 struct B
35     : public A
36 {
37     static int count;
BB38     B() {++count;}
BB39     B(const B&) {++count;}
~BB40     virtual ~B() {--count;}
41 };
42 
43 int B::count = 0;
44 
45 template <class T>
46 class Deleter
47 {
48     int state_;
49 
50 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
51     Deleter(const Deleter&);
52     Deleter& operator=(const Deleter&);
53 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
54     Deleter(Deleter&);
55     Deleter& operator=(Deleter&);
56 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
57 
58 public:
59 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Deleter(Deleter && r)60     Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
operator =(Deleter && r)61     Deleter& operator=(Deleter&& r)
62     {
63         state_ = r.state_;
64         r.state_ = 0;
65         return *this;
66     }
67 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
68     operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);}
69     Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;}
70     Deleter& operator=(std::__rv<Deleter> r)
71     {
72         state_ = r->state_;
73         r->state_ = 0;
74         return *this;
75     }
76 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
77 
Deleter()78     Deleter() : state_(5) {}
79 
80 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
81     template <class U>
Deleter(Deleter<U> && d,typename std::enable_if<!std::is_same<U,T>::value>::type * =0)82         Deleter(Deleter<U>&& d,
83             typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
84             : state_(d.state()) {d.set_state(0);}
85 
86 private:
87     template <class U>
88         Deleter(const Deleter<U>& d,
89             typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
90 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
91     template <class U>
Deleter(Deleter<U> d,typename std::enable_if<!std::is_same<U,T>::value>::type * =0)92         Deleter(Deleter<U> d,
93             typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
94             : state_(d.state()) {}
95 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
96 public:
state() const97     int state() const {return state_;}
set_state(int i)98     void set_state(int i) {state_ = i;}
99 
operator ()(T * p)100     void operator()(T* p) {delete p;}
101 };
102 
main()103 int main()
104 {
105     {
106     const std::unique_ptr<B, Deleter<B> > s(new B);
107     A* p = s.get();
108     std::unique_ptr<A, Deleter<A> > s2 = s;
109     assert(s2.get() == p);
110     assert(s.get() == 0);
111     assert(A::count == 1);
112     assert(B::count == 1);
113     assert(s2.get_deleter().state() == 5);
114     assert(s.get_deleter().state() == 0);
115     }
116     assert(A::count == 0);
117     assert(B::count == 0);
118 }
119