1c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//===----------------------------------------------------------------------===//
2c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//
3c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//                     The LLVM Compiler Infrastructure
4c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//
5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// Source Licenses. See LICENSE.TXT for details.
7c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//
8c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant//===----------------------------------------------------------------------===//
9c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
10c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant// <memory>
11c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
12c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant// unique_ptr
13c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
14c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant// Example move-only deleter
15c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
16c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#ifndef DELETER_H
17c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#define DELETER_H
18c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
19c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include <type_traits>
20c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#include <cassert>
21c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
22c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnanttemplate <class T>
23c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantclass Deleter
24c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant{
25c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    int state_;
26c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
2773d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
28c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter(const Deleter&);
29c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter& operator=(const Deleter&);
3073d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
31c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter(Deleter&);
32c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter& operator=(Deleter&);
3373d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
34c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
35c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantpublic:
3673d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
37c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
38c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter& operator=(Deleter&& r)
39c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    {
40c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        state_ = r.state_;
41c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        r.state_ = 0;
42c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        return *this;
43c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    }
4473d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
45c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);}
46c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;}
47c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter& operator=(std::__rv<Deleter> r)
48c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    {
49c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        state_ = r->state_;
50c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        r->state_ = 0;
51c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        return *this;
52c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    }
5373d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
54c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
55c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter() : state_(0) {}
56c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    explicit Deleter(int s) : state_(s) {}
57c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    ~Deleter() {assert(state_ >= 0); state_ = -1;}
58c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
5973d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
60c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    template <class U>
61c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        Deleter(Deleter<U>&& d,
62c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
63c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant            : state_(d.state()) {d.set_state(0);}
64c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
65c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantprivate:
66c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    template <class U>
67c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        Deleter(const Deleter<U>& d,
68c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
6973d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
70c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    template <class U>
71c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        Deleter(Deleter<U> d,
72c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant            typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
73c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant            : state_(d.state()) {}
7473d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
75c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantpublic:
76c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    int state() const {return state_;}
77c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    void set_state(int i) {state_ = i;}
78c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
79c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    void operator()(T* p) {delete p;}
80c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant};
81c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
82c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnanttemplate <class T>
83c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantclass Deleter<T[]>
84c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant{
85c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    int state_;
86c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
8773d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
88c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter(const Deleter&);
89c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter& operator=(const Deleter&);
9073d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
91c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter(Deleter&);
92c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter& operator=(Deleter&);
9373d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
94c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
95c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantpublic:
9673d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
97c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
98c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter& operator=(Deleter&& r)
99c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    {
100c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        state_ = r.state_;
101c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        r.state_ = 0;
102c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        return *this;
103c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    }
10473d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
105c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);}
106c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;}
107c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter& operator=(std::__rv<Deleter> r)
108c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    {
109c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        state_ = r->state_;
110c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        r->state_ = 0;
111c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        return *this;
112c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    }
11373d21a4f0774d3fadab98e690619a359cfb160a3Howard Hinnant#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
114c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
115c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter() : state_(0) {}
116c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    explicit Deleter(int s) : state_(s) {}
117c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    ~Deleter() {assert(state_ >= 0); state_ = -1;}
118c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
119c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    int state() const {return state_;}
120c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    void set_state(int i) {state_ = i;}
121c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
122c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    void operator()(T* p) {delete [] p;}
123c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant};
124c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
125c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnanttemplate <class T>
126c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantvoid
127c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantswap(Deleter<T>& x, Deleter<T>& y)
128c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant{
129c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    Deleter<T> t(std::move(x));
130c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    x = std::move(y);
131c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    y = std::move(t);
132c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant}
133c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
134c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnanttemplate <class T>
135c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantclass CDeleter
136c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant{
137c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    int state_;
138c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
139c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantpublic:
140c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
141c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    CDeleter() : state_(0) {}
142c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    explicit CDeleter(int s) : state_(s) {}
143c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    ~CDeleter() {assert(state_ >= 0); state_ = -1;}
144c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
145c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    template <class U>
146c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant        CDeleter(const CDeleter<U>& d)
147c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant            : state_(d.state()) {}
148c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
149c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    int state() const {return state_;}
150c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    void set_state(int i) {state_ = i;}
151c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
152c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    void operator()(T* p) {delete p;}
153c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant};
154c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
155c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnanttemplate <class T>
156c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantclass CDeleter<T[]>
157c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant{
158c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    int state_;
159c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
160c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantpublic:
161c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
162c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    CDeleter() : state_(0) {}
163c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    explicit CDeleter(int s) : state_(s) {}
164c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    ~CDeleter() {assert(state_ >= 0); state_ = -1;}
165c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
166c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    int state() const {return state_;}
167c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    void set_state(int i) {state_ = i;}
168c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
169c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    void operator()(T* p) {delete [] p;}
170c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant};
171c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
172c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnanttemplate <class T>
173c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantvoid
174c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnantswap(CDeleter<T>& x, CDeleter<T>& y)
175c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant{
176c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    CDeleter<T> t(std::move(x));
177c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    x = std::move(y);
178c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant    y = std::move(t);
179c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant}
180c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant
181c52f43e72dfcea03037729649da84c23b3beb04aHoward Hinnant#endif  // DELETER_H
182