111
|
1 /* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
|
|
2
|
145
|
3 Copyright (C) 2007-2020 Free Software Foundation, Inc.
|
111
|
4
|
|
5 This file is part of GCC.
|
|
6
|
|
7 This program is free software; you can redistribute it and/or modify
|
|
8 it under the terms of the GNU General Public License as published by
|
|
9 the Free Software Foundation; either version 3 of the License, or
|
|
10 (at your option) any later version.
|
|
11
|
|
12 This program is distributed in the hope that it will be useful,
|
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 GNU General Public License for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
19
|
|
20 /* gnu::unique_ptr defines a C++ owning smart pointer that exposes a
|
|
21 subset of the std::unique_ptr API.
|
|
22
|
|
23 In fact, when compiled with a C++11 compiler, gnu::unique_ptr
|
|
24 actually _is_ std::unique_ptr. When compiled with a C++03 compiler
|
|
25 OTOH, it's an hand coded std::unique_ptr emulation that assumes
|
|
26 code is correct and doesn't try to be too smart.
|
|
27
|
|
28 This supports custom deleters, but not _stateful_ deleters, so you
|
|
29 can't use those in C++11 mode either. Only the managed pointer is
|
|
30 stored in the smart pointer. That could be changed; it simply
|
|
31 wasn't found necessary.
|
|
32
|
|
33 At the end of the file you'll find a gnu::unique_ptr partial
|
|
34 specialization that uses a custom (stateless) deleter:
|
|
35 gnu::unique_xmalloc_ptr. That is used to manage pointers to
|
|
36 objects allocated with xmalloc.
|
|
37
|
|
38 The C++03 version was originally based on GCC 7.0's std::auto_ptr
|
|
39 and then heavily customized to behave more like C++11's
|
|
40 std::unique_ptr, but at this point, it no longer shares much at all
|
|
41 with the original file. But, that's the history and the reason for
|
|
42 the copyright's starting year.
|
|
43
|
|
44 The C++03 version lets you shoot yourself in the foot, since
|
|
45 similarly to std::auto_ptr, the copy constructor and assignment
|
|
46 operators actually move. Also, in the name of simplicity, no
|
|
47 effort is spent on using SFINAE to prevent invalid conversions,
|
|
48 etc. This is not really a problem, because the goal here is to
|
|
49 allow code that would be correct using std::unique_ptr to be
|
|
50 equally correct in C++03 mode, and, just as efficient. If client
|
|
51 code compiles correctly with a C++11 (or newer) compiler, we know
|
|
52 we're not doing anything invalid by mistake.
|
|
53
|
|
54 Usage notes:
|
|
55
|
|
56 - Putting gnu::unique_ptr in standard containers is not supported,
|
|
57 since C++03 containers are not move-aware (and our emulation
|
|
58 relies on copy actually moving).
|
|
59
|
|
60 - Since there's no nullptr in C++03, gnu::unique_ptr allows
|
|
61 implicit initialization and assignment from NULL instead.
|
|
62
|
|
63 - To check whether there's an associated managed object, all these
|
|
64 work as expected:
|
|
65
|
|
66 if (ptr)
|
|
67 if (!ptr)
|
|
68 if (ptr != NULL)
|
|
69 if (ptr == NULL)
|
|
70 if (NULL != ptr)
|
|
71 if (NULL == ptr)
|
|
72 */
|
|
73
|
|
74 #ifndef GNU_UNIQUE_PTR_H
|
|
75 #define GNU_UNIQUE_PTR_H 1
|
|
76
|
|
77 #if __cplusplus >= 201103
|
|
78 # include <memory>
|
|
79 #endif
|
|
80
|
|
81 namespace gnu
|
|
82 {
|
|
83
|
|
84 #if __cplusplus >= 201103
|
|
85
|
|
86 /* In C++11 mode, all we need is import the standard
|
|
87 std::unique_ptr. */
|
|
88 template<typename T> using unique_ptr = std::unique_ptr<T>;
|
|
89
|
|
90 /* Pull in move as well. */
|
|
91 using std::move;
|
|
92
|
|
93 #else /* C++11 */
|
|
94
|
|
95 /* Default destruction policy used by gnu::unique_ptr when no deleter
|
|
96 is specified. Uses delete. */
|
|
97
|
|
98 template<typename T>
|
|
99 struct default_delete
|
|
100 {
|
|
101 void operator () (T *ptr) const { delete ptr; }
|
|
102 };
|
|
103
|
|
104 /* Specialization for arrays. Uses delete[]. */
|
|
105
|
|
106 template<typename T>
|
|
107 struct default_delete<T[]>
|
|
108 {
|
|
109 void operator () (T *ptr) const { delete [] ptr; }
|
|
110 };
|
|
111
|
|
112 namespace detail
|
|
113 {
|
|
114 /* Type used to support implicit construction from NULL:
|
|
115
|
|
116 gnu::unique_ptr<foo> func (....)
|
|
117 {
|
|
118 return NULL;
|
|
119 }
|
|
120
|
|
121 and assignment from NULL:
|
|
122
|
|
123 gnu::unique_ptr<foo> ptr (....);
|
|
124 ...
|
|
125 ptr = NULL;
|
|
126
|
|
127 It is intentionally not defined anywhere. */
|
|
128 struct nullptr_t;
|
|
129
|
|
130 /* Base class of our unique_ptr emulation. Contains code common to
|
|
131 both unique_ptr<T, D> and unique_ptr<T[], D>. */
|
|
132
|
|
133 template<typename T, typename D>
|
|
134 class unique_ptr_base
|
|
135 {
|
|
136 public:
|
|
137 typedef T *pointer;
|
|
138 typedef T element_type;
|
|
139 typedef D deleter_type;
|
|
140
|
|
141 /* Takes ownership of a pointer. P is a pointer to an object of
|
|
142 element_type type. Defaults to NULL. */
|
|
143 explicit unique_ptr_base (element_type *p = NULL) throw () : m_ptr (p) {}
|
|
144
|
|
145 /* The "move" constructor. Really a copy constructor that actually
|
|
146 moves. Even though std::unique_ptr is not copyable, our little
|
|
147 simpler emulation allows it, because:
|
|
148
|
|
149 - There are no rvalue references in C++03. Our move emulation
|
|
150 instead relies on copy/assignment moving, like std::auto_ptr.
|
|
151 - RVO/NRVO requires an accessible copy constructor
|
|
152 */
|
|
153 unique_ptr_base (const unique_ptr_base &other) throw ()
|
|
154 : m_ptr (const_cast<unique_ptr_base &> (other).release ()) {}
|
|
155
|
|
156 /* Converting "move" constructor. Really an lvalue ref converting
|
|
157 constructor that actually moves. This allows constructs such as:
|
|
158
|
|
159 unique_ptr<Derived> func_returning_unique_ptr (.....);
|
|
160 ...
|
|
161 unique_ptr<Base> ptr = func_returning_unique_ptr (.....);
|
|
162 */
|
|
163 template<typename T1, typename D1>
|
|
164 unique_ptr_base (const unique_ptr_base<T1, D1> &other) throw ()
|
|
165 : m_ptr (const_cast<unique_ptr_base<T1, D1> &> (other).release ()) {}
|
|
166
|
|
167 /* The "move" assignment operator. Really an lvalue ref copy
|
|
168 assignment operator that actually moves. See comments above. */
|
|
169 unique_ptr_base &operator= (const unique_ptr_base &other) throw ()
|
|
170 {
|
|
171 reset (const_cast<unique_ptr_base &> (other).release ());
|
|
172 return *this;
|
|
173 }
|
|
174
|
|
175 /* Converting "move" assignment. Really an lvalue ref converting
|
|
176 copy assignment operator that moves. See comments above. */
|
|
177 template<typename T1, typename D1>
|
|
178 unique_ptr_base &operator= (const unique_ptr_base<T1, D1> &other) throw ()
|
|
179 {
|
|
180 reset (const_cast<unique_ptr_base<T1, D1> &> (other).release ());
|
|
181 return *this;
|
|
182 }
|
|
183
|
|
184 /* std::unique_ptr does not allow assignment, except from nullptr.
|
|
185 nullptr doesn't exist in C++03, so we allow assignment from NULL
|
|
186 instead [ptr = NULL;].
|
|
187 */
|
|
188 unique_ptr_base &operator= (detail::nullptr_t *) throw ()
|
|
189 {
|
|
190 reset ();
|
|
191 return *this;
|
|
192 }
|
|
193
|
|
194 ~unique_ptr_base () { call_deleter (); }
|
|
195
|
|
196 /* "explicit operator bool ()" emulation using the safe bool
|
|
197 idiom. */
|
|
198 private:
|
|
199 typedef void (unique_ptr_base::*explicit_operator_bool) () const;
|
|
200 void this_type_does_not_support_comparisons () const {}
|
|
201
|
|
202 public:
|
|
203 operator explicit_operator_bool () const
|
|
204 {
|
|
205 return (m_ptr != NULL
|
|
206 ? &unique_ptr_base::this_type_does_not_support_comparisons
|
|
207 : 0);
|
|
208 }
|
|
209
|
|
210 element_type *get () const throw () { return m_ptr; }
|
|
211
|
|
212 element_type *release () throw ()
|
|
213 {
|
|
214 pointer tmp = m_ptr;
|
|
215 m_ptr = NULL;
|
|
216 return tmp;
|
|
217 }
|
|
218
|
|
219 void reset (element_type *p = NULL) throw ()
|
|
220 {
|
|
221 if (p != m_ptr)
|
|
222 {
|
|
223 call_deleter ();
|
|
224 m_ptr = p;
|
|
225 }
|
|
226 }
|
|
227
|
|
228 private:
|
|
229
|
|
230 /* Call the deleter. Note we assume the deleter is "stateless". */
|
|
231 void call_deleter ()
|
|
232 {
|
|
233 D d;
|
|
234
|
|
235 d (m_ptr);
|
|
236 }
|
|
237
|
|
238 element_type *m_ptr;
|
|
239 };
|
|
240
|
|
241 } /* namespace detail */
|
|
242
|
|
243 /* Macro used to create a unique_ptr_base "partial specialization" --
|
|
244 a subclass that uses a specific deleter. Basically this re-defines
|
|
245 the necessary constructors. This is necessary because C++03
|
|
246 doesn't support inheriting constructors with "using". While at it,
|
|
247 we inherit the assignment operator. TYPE is the name of the type
|
|
248 being defined. Assumes that 'base_type' is a typedef of the
|
|
249 baseclass TYPE is inheriting from. */
|
|
250 #define DEFINE_GNU_UNIQUE_PTR(TYPE) \
|
|
251 public: \
|
|
252 explicit TYPE (T *p = NULL) throw () \
|
|
253 : base_type (p) {} \
|
|
254 \
|
|
255 TYPE (const TYPE &other) throw () : base_type (other) {} \
|
|
256 \
|
|
257 TYPE (detail::nullptr_t *) throw () : base_type (NULL) {} \
|
|
258 \
|
|
259 template<typename T1, typename D1> \
|
|
260 TYPE (const detail::unique_ptr_base<T1, D1> &other) throw () \
|
|
261 : base_type (other) {} \
|
|
262 \
|
|
263 using base_type::operator=;
|
|
264
|
|
265 /* Define single-object gnu::unique_ptr. */
|
|
266
|
|
267 template <typename T, typename D = default_delete<T> >
|
|
268 class unique_ptr : public detail::unique_ptr_base<T, D>
|
|
269 {
|
|
270 typedef detail::unique_ptr_base<T, D> base_type;
|
|
271
|
|
272 DEFINE_GNU_UNIQUE_PTR (unique_ptr)
|
|
273
|
|
274 public:
|
|
275 /* Dereferencing. */
|
|
276 T &operator* () const throw () { return *this->get (); }
|
|
277 T *operator-> () const throw () { return this->get (); }
|
|
278 };
|
|
279
|
|
280 /* Define gnu::unique_ptr specialization for T[]. */
|
|
281
|
|
282 template <typename T, typename D>
|
|
283 class unique_ptr<T[], D> : public detail::unique_ptr_base<T, D>
|
|
284 {
|
|
285 typedef detail::unique_ptr_base<T, D> base_type;
|
|
286
|
|
287 DEFINE_GNU_UNIQUE_PTR (unique_ptr)
|
|
288
|
|
289 public:
|
|
290 /* Indexing operator. */
|
|
291 T &operator[] (size_t i) const { return this->get ()[i]; }
|
|
292 };
|
|
293
|
|
294 /* Comparison operators. */
|
|
295
|
|
296 template <typename T, typename D,
|
|
297 typename U, typename E>
|
|
298 inline bool
|
|
299 operator== (const detail::unique_ptr_base<T, D> &x,
|
|
300 const detail::unique_ptr_base<U, E> &y)
|
|
301 { return x.get() == y.get(); }
|
|
302
|
|
303 template <typename T, typename D,
|
|
304 typename U, typename E>
|
|
305 inline bool
|
|
306 operator!= (const detail::unique_ptr_base<T, D> &x,
|
|
307 const detail::unique_ptr_base<U, E> &y)
|
|
308 { return x.get() != y.get(); }
|
|
309
|
|
310 template<typename T, typename D,
|
|
311 typename U, typename E>
|
|
312 inline bool
|
|
313 operator< (const detail::unique_ptr_base<T, D> &x,
|
|
314 const detail::unique_ptr_base<U, E> &y)
|
|
315 { return x.get() < y.get (); }
|
|
316
|
|
317 template<typename T, typename D,
|
|
318 typename U, typename E>
|
|
319 inline bool
|
|
320 operator<= (const detail::unique_ptr_base<T, D> &x,
|
|
321 const detail::unique_ptr_base<U, E> &y)
|
|
322 { return !(y < x); }
|
|
323
|
|
324 template<typename T, typename D,
|
|
325 typename U, typename E>
|
|
326 inline bool
|
|
327 operator> (const detail::unique_ptr_base<T, D> &x,
|
|
328 const detail::unique_ptr_base<U, E> &y)
|
|
329 { return y < x; }
|
|
330
|
|
331 template<typename T, typename D,
|
|
332 typename U, typename E>
|
|
333 inline bool
|
|
334 operator>= (const detail::unique_ptr_base<T, D> &x,
|
|
335 const detail::unique_ptr_base<U, E> &y)
|
|
336 { return !(x < y); }
|
|
337
|
|
338 /* std::move "emulation". This is as simple as it can be -- no
|
145
|
339 attempt is made to emulate rvalue references. This relies on T
|
|
340 having move semantics like std::auto_ptr.
|
|
341 I.e., copy/assignment actually moves. */
|
111
|
342
|
145
|
343 template<typename T>
|
|
344 const T&
|
|
345 move (T& v)
|
111
|
346 {
|
|
347 return v;
|
|
348 }
|
|
349
|
|
350 #endif /* C++11 */
|
|
351
|
|
352 /* Define gnu::unique_xmalloc_ptr, a gnu::unique_ptr that manages
|
|
353 xmalloc'ed memory. */
|
|
354
|
|
355 /* The deleter for gnu::unique_xmalloc_ptr. Uses free. */
|
|
356 template <typename T>
|
|
357 struct xmalloc_deleter
|
|
358 {
|
|
359 void operator() (T *ptr) const { free (ptr); }
|
|
360 };
|
|
361
|
|
362 /* Same, for arrays. */
|
|
363 template <typename T>
|
|
364 struct xmalloc_deleter<T[]>
|
|
365 {
|
|
366 void operator() (T *ptr) const { free (ptr); }
|
|
367 };
|
|
368
|
|
369 #if __cplusplus >= 201103
|
|
370
|
|
371 /* In C++11, we just import the standard unique_ptr to our namespace
|
|
372 with a custom deleter. */
|
|
373
|
|
374 template<typename T> using unique_xmalloc_ptr
|
|
375 = std::unique_ptr<T, xmalloc_deleter<T>>;
|
|
376
|
|
377 #else /* C++11 */
|
|
378
|
|
379 /* In C++03, we don't have template aliases, so we need to define a
|
|
380 subclass instead, and re-define the constructors, because C++03
|
|
381 doesn't support inheriting constructors either. */
|
|
382
|
|
383 template <typename T>
|
|
384 class unique_xmalloc_ptr : public unique_ptr<T, xmalloc_deleter<T> >
|
|
385 {
|
|
386 typedef unique_ptr<T, xmalloc_deleter<T> > base_type;
|
|
387
|
|
388 DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
|
|
389 };
|
|
390
|
|
391 /* Define gnu::unique_xmalloc_ptr specialization for T[]. */
|
|
392
|
|
393 template <typename T>
|
|
394 class unique_xmalloc_ptr<T[]> : public unique_ptr<T[], xmalloc_deleter<T[]> >
|
|
395 {
|
|
396 typedef unique_ptr<T[], xmalloc_deleter<T[]> > base_type;
|
|
397
|
|
398 DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
|
|
399 };
|
|
400
|
|
401 #endif /* C++11 */
|
|
402
|
|
403 } /* namespace gnu */
|
|
404
|
|
405 #endif /* GNU_UNIQUE_PTR_H */
|