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