move01.pass.cpp revision c52f43e72dfcea03037729649da84c23b3beb04a
1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// <memory>
11
12// unique_ptr
13
14// Test unique_ptr move ctor
15
16#include <memory>
17#include <cassert>
18
19// test move ctor.  Should only require a MoveConstructible deleter, or if
20//    deleter is a reference, not even that.
21
22struct A
23{
24    static int count;
25    A() {++count;}
26    A(const A&) {++count;}
27    ~A() {--count;}
28};
29
30int A::count = 0;
31
32template <class T>
33class Deleter
34{
35    int state_;
36
37#ifdef _LIBCPP_MOVE
38    Deleter(const Deleter&);
39    Deleter& operator=(const Deleter&);
40#else  // _LIBCPP_MOVE
41    Deleter(Deleter&);
42    Deleter& operator=(Deleter&);
43#endif  // _LIBCPP_MOVE
44
45public:
46#ifdef _LIBCPP_MOVE
47    Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
48    Deleter& operator=(Deleter&& r)
49    {
50        state_ = r.state_;
51        r.state_ = 0;
52        return *this;
53    }
54#else  // _LIBCPP_MOVE
55    operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);}
56    Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;}
57    Deleter& operator=(std::__rv<Deleter> r)
58    {
59        state_ = r->state_;
60        r->state_ = 0;
61        return *this;
62    }
63#endif  // _LIBCPP_MOVE
64
65    Deleter() : state_(5) {}
66
67#ifdef _LIBCPP_MOVE
68    template <class U>
69        Deleter(Deleter<U>&& d,
70            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
71            : state_(d.state()) {d.set_state(0);}
72
73private:
74    template <class U>
75        Deleter(const Deleter<U>& d,
76            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
77#else  // _LIBCPP_MOVE
78    template <class U>
79        Deleter(Deleter<U> d,
80            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
81            : state_(d.state()) {}
82#endif  // _LIBCPP_MOVE
83public:
84    int state() const {return state_;}
85    void set_state(int i) {state_ = i;}
86
87    void operator()(T* p) {delete p;}
88};
89
90class CDeleter
91{
92    int state_;
93
94    CDeleter(CDeleter&);
95    CDeleter& operator=(CDeleter&);
96public:
97
98    CDeleter() : state_(5) {}
99
100    int state() const {return state_;}
101    void set_state(int s) {state_ = s;}
102
103    void operator()(A* p) {delete p;}
104};
105
106int main()
107{
108    {
109    std::unique_ptr<A> s(new A);
110    A* p = s.get();
111    std::unique_ptr<A> s2 = std::move(s);
112    assert(s2.get() == p);
113    assert(s.get() == 0);
114    assert(A::count == 1);
115    }
116    assert(A::count == 0);
117    {
118    std::unique_ptr<A, Deleter<A> > s(new A);
119    A* p = s.get();
120    std::unique_ptr<A, Deleter<A> > s2 = std::move(s);
121    assert(s2.get() == p);
122    assert(s.get() == 0);
123    assert(A::count == 1);
124    assert(s2.get_deleter().state() == 5);
125    assert(s.get_deleter().state() == 0);
126    }
127    assert(A::count == 0);
128    {
129    CDeleter d;
130    std::unique_ptr<A, CDeleter&> s(new A, d);
131    A* p = s.get();
132    std::unique_ptr<A, CDeleter&> s2 = std::move(s);
133    assert(s2.get() == p);
134    assert(s.get() == 0);
135    assert(A::count == 1);
136    d.set_state(6);
137    assert(s2.get_deleter().state() == d.state());
138    assert(s.get_deleter().state() ==  d.state());
139    }
140    assert(A::count == 0);
141}
142