]>
Commit | Line | Data |
---|---|---|
46d2b77d DM |
1 | /* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03. |
2 | ||
85ec4feb | 3 | Copyright (C) 2007-2018 Free Software Foundation, Inc. |
46d2b77d DM |
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 | ||
b367de5d DM |
77 | #if __cplusplus >= 201103 |
78 | # include <memory> | |
79 | #endif | |
46d2b77d DM |
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 | |
339 | attempt is made to emulate rvalue references. Instead relies on | |
340 | the fact that gnu::unique_ptr has move semantics like | |
341 | std::auto_ptr. I.e., copy/assignment actually moves. */ | |
342 | ||
343 | template<typename T, typename D> | |
344 | unique_ptr<T, D> | |
345 | move (unique_ptr<T, D> v) | |
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 */ |