Commit | Line | Data |
---|---|---|
da804164 PA |
1 | /* gdb::unique_ptr, a simple std::unique_ptr replacement for C++03. |
2 | ||
3 | Copyright (C) 2007-2016 Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of GDB. | |
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 | /* gdb::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, gdb::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 gdb::unique_ptr partial | |
34 | specialization that uses a custom (stateless) deleter: | |
35 | gdb::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 gdb::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, gdb::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 GDB_UNIQUE_PTR_H | |
75 | #define GDB_UNIQUE_PTR_H 1 | |
76 | ||
77 | #include <memory> | |
78 | ||
79 | namespace gdb | |
80 | { | |
81 | ||
82 | #if __cplusplus >= 201103 | |
83 | ||
84 | /* In C++11 mode, all we need is import the standard | |
85 | std::unique_ptr. */ | |
86 | template<typename T> using unique_ptr = std::unique_ptr<T>; | |
87 | ||
88 | /* Pull in move as well. */ | |
89 | using std::move; | |
90 | ||
91 | #else /* C++11 */ | |
92 | ||
93 | /* Default destruction policy used by gdb::unique_ptr when no deleter | |
94 | is specified. Uses delete. */ | |
95 | ||
96 | template<typename T> | |
97 | struct default_delete | |
98 | { | |
99 | void operator () (T *ptr) const { delete ptr; } | |
100 | }; | |
101 | ||
102 | /* Specialization for arrays. Uses delete[]. */ | |
103 | ||
104 | template<typename T> | |
105 | struct default_delete<T[]> | |
106 | { | |
107 | void operator () (T *ptr) const { delete [] ptr; } | |
108 | }; | |
109 | ||
110 | namespace detail | |
111 | { | |
112 | /* Type used to support implicit construction from NULL: | |
113 | ||
114 | gdb::unique_ptr<foo> func (....) | |
115 | { | |
116 | return NULL; | |
117 | } | |
118 | ||
119 | and assignment from NULL: | |
120 | ||
121 | gdb::unique_ptr<foo> ptr (....); | |
122 | ... | |
123 | ptr = NULL; | |
124 | ||
125 | It is intentionally not defined anywhere. */ | |
126 | struct nullptr_t; | |
127 | ||
128 | /* Base class of our unique_ptr emulation. Contains code common to | |
129 | both unique_ptr<T, D> and unique_ptr<T[], D>. */ | |
130 | ||
131 | template<typename T, typename D> | |
132 | class unique_ptr_base | |
133 | { | |
134 | public: | |
135 | typedef T *pointer; | |
136 | typedef T element_type; | |
137 | typedef D deleter_type; | |
138 | ||
139 | /* Takes ownership of a pointer. P is a pointer to an object of | |
140 | element_type type. Defaults to NULL. */ | |
141 | explicit unique_ptr_base (element_type *p = NULL) throw () : m_ptr (p) {} | |
142 | ||
143 | /* The "move" constructor. Really a copy constructor that actually | |
144 | moves. Even though std::unique_ptr is not copyable, our little | |
145 | simpler emulation allows it, because: | |
146 | ||
147 | - There are no rvalue references in C++03. Our move emulation | |
148 | instead relies on copy/assignment moving, like std::auto_ptr. | |
149 | - RVO/NRVO requires an accessible copy constructor | |
150 | */ | |
151 | unique_ptr_base (const unique_ptr_base &other) throw () | |
152 | : m_ptr (const_cast<unique_ptr_base &> (other).release ()) {} | |
153 | ||
154 | /* Converting "move" constructor. Really an lvalue ref converting | |
155 | constructor that actually moves. This allows constructs such as: | |
156 | ||
157 | unique_ptr<Derived> func_returning_unique_ptr (.....); | |
158 | ... | |
159 | unique_ptr<Base> ptr = func_returning_unique_ptr (.....); | |
160 | */ | |
161 | template<typename T1, typename D1> | |
162 | unique_ptr_base (const unique_ptr_base<T1, D1> &other) throw () | |
163 | : m_ptr (const_cast<unique_ptr_base<T1, D1> &> (other).release ()) {} | |
164 | ||
165 | /* The "move" assignment operator. Really an lvalue ref copy | |
166 | assignment operator that actually moves. See comments above. */ | |
167 | unique_ptr_base &operator= (const unique_ptr_base &other) throw () | |
168 | { | |
169 | reset (const_cast<unique_ptr_base &> (other).release ()); | |
170 | return *this; | |
171 | } | |
172 | ||
173 | /* Converting "move" assignment. Really an lvalue ref converting | |
174 | copy assignment operator that moves. See comments above. */ | |
175 | template<typename T1, typename D1> | |
176 | unique_ptr_base &operator= (const unique_ptr_base<T1, D1> &other) throw () | |
177 | { | |
178 | reset (const_cast<unique_ptr_base<T1, D1> &> (other).release ()); | |
179 | return *this; | |
180 | } | |
181 | ||
182 | /* std::unique_ptr does not allow assignment, except from nullptr. | |
183 | nullptr doesn't exist in C++03, so we allow assignment from NULL | |
184 | instead [ptr = NULL;]. | |
185 | */ | |
186 | unique_ptr_base &operator= (detail::nullptr_t *) throw () | |
187 | { | |
188 | reset (); | |
189 | return *this; | |
190 | } | |
191 | ||
192 | ~unique_ptr_base () { call_deleter (); } | |
193 | ||
194 | /* "explicit operator bool ()" emulation using the safe bool | |
195 | idiom. */ | |
196 | private: | |
197 | typedef void (unique_ptr_base::*explicit_operator_bool) () const; | |
198 | void this_type_does_not_support_comparisons () const {} | |
199 | ||
200 | public: | |
201 | operator explicit_operator_bool () const | |
202 | { | |
203 | return (m_ptr != NULL | |
204 | ? &unique_ptr_base::this_type_does_not_support_comparisons | |
205 | : 0); | |
206 | } | |
207 | ||
208 | element_type *get () const throw () { return m_ptr; } | |
209 | ||
210 | element_type *release () throw () | |
211 | { | |
212 | pointer tmp = m_ptr; | |
213 | m_ptr = NULL; | |
214 | return tmp; | |
215 | } | |
216 | ||
217 | void reset (element_type *p = NULL) throw () | |
218 | { | |
219 | if (p != m_ptr) | |
220 | { | |
221 | call_deleter (); | |
222 | m_ptr = p; | |
223 | } | |
224 | } | |
225 | ||
226 | private: | |
227 | ||
228 | /* Call the deleter. Note we assume the deleter is "stateless". */ | |
229 | void call_deleter () | |
230 | { | |
231 | D d; | |
232 | ||
233 | d (m_ptr); | |
234 | } | |
235 | ||
236 | element_type *m_ptr; | |
237 | }; | |
238 | ||
239 | } /* namespace detail */ | |
240 | ||
241 | /* Macro used to create a unique_ptr_base "partial specialization" -- | |
242 | a subclass that uses a specific deleter. Basically this re-defines | |
243 | the necessary constructors. This is necessary because C++03 | |
244 | doesn't support inheriting constructors with "using". While at it, | |
245 | we inherit the assignment operator. TYPE is the name of the type | |
246 | being defined. Assumes that 'base_type' is a typedef of the | |
247 | baseclass TYPE is inheriting from. */ | |
248 | #define DEFINE_GDB_UNIQUE_PTR(TYPE) \ | |
249 | public: \ | |
250 | explicit TYPE (T *p = NULL) throw () \ | |
251 | : base_type (p) {} \ | |
252 | \ | |
253 | TYPE (const TYPE &other) throw () : base_type (other) {} \ | |
254 | \ | |
255 | TYPE (detail::nullptr_t *) throw () : base_type (NULL) {} \ | |
256 | \ | |
257 | template<typename T1, typename D1> \ | |
258 | TYPE (const detail::unique_ptr_base<T1, D1> &other) throw () \ | |
259 | : base_type (other) {} \ | |
260 | \ | |
261 | using base_type::operator=; | |
262 | ||
263 | /* Define single-object gdb::unique_ptr. */ | |
264 | ||
265 | template <typename T, typename D = default_delete<T> > | |
266 | class unique_ptr : public detail::unique_ptr_base<T, D> | |
267 | { | |
268 | typedef detail::unique_ptr_base<T, D> base_type; | |
269 | ||
270 | DEFINE_GDB_UNIQUE_PTR (unique_ptr) | |
271 | ||
272 | public: | |
273 | /* Dereferencing. */ | |
274 | T &operator* () const throw () { return *this->get (); } | |
275 | T *operator-> () const throw () { return this->get (); } | |
276 | }; | |
277 | ||
278 | /* Define gdb::unique_ptr specialization for T[]. */ | |
279 | ||
280 | template <typename T, typename D> | |
281 | class unique_ptr<T[], D> : public detail::unique_ptr_base<T, D> | |
282 | { | |
283 | typedef detail::unique_ptr_base<T, D> base_type; | |
284 | ||
285 | DEFINE_GDB_UNIQUE_PTR (unique_ptr) | |
286 | ||
287 | public: | |
288 | /* Indexing operator. */ | |
289 | T &operator[] (size_t i) const { return this->get ()[i]; } | |
290 | }; | |
291 | ||
292 | /* Comparison operators. */ | |
293 | ||
294 | template <typename T, typename D, | |
295 | typename U, typename E> | |
296 | inline bool | |
297 | operator== (const detail::unique_ptr_base<T, D> &x, | |
298 | const detail::unique_ptr_base<U, E> &y) | |
299 | { return x.get() == y.get(); } | |
300 | ||
301 | template <typename T, typename D, | |
302 | typename U, typename E> | |
303 | inline bool | |
304 | operator!= (const detail::unique_ptr_base<T, D> &x, | |
305 | const detail::unique_ptr_base<U, E> &y) | |
306 | { return x.get() != y.get(); } | |
307 | ||
308 | template<typename T, typename D, | |
309 | typename U, typename E> | |
310 | inline bool | |
311 | operator< (const detail::unique_ptr_base<T, D> &x, | |
312 | const detail::unique_ptr_base<U, E> &y) | |
313 | { return x.get() < y.get (); } | |
314 | ||
315 | template<typename T, typename D, | |
316 | typename U, typename E> | |
317 | inline bool | |
318 | operator<= (const detail::unique_ptr_base<T, D> &x, | |
319 | const detail::unique_ptr_base<U, E> &y) | |
320 | { return !(y < x); } | |
321 | ||
322 | template<typename T, typename D, | |
323 | typename U, typename E> | |
324 | inline bool | |
325 | operator> (const detail::unique_ptr_base<T, D> &x, | |
326 | const detail::unique_ptr_base<U, E> &y) | |
327 | { return y < x; } | |
328 | ||
329 | template<typename T, typename D, | |
330 | typename U, typename E> | |
331 | inline bool | |
332 | operator>= (const detail::unique_ptr_base<T, D> &x, | |
333 | const detail::unique_ptr_base<U, E> &y) | |
334 | { return !(x < y); } | |
335 | ||
336 | /* std::move "emulation". This is as simple as it can be -- no | |
337 | attempt is made to emulate rvalue references. Instead relies on | |
338 | the fact that gdb::unique_ptr has move semantics like | |
339 | std::auto_ptr. I.e., copy/assignment actually moves. */ | |
340 | ||
341 | template<typename T, typename D> | |
342 | unique_ptr<T, D> | |
343 | move (unique_ptr<T, D> v) | |
344 | { | |
345 | return v; | |
346 | } | |
347 | ||
348 | #endif /* C++11 */ | |
349 | ||
350 | /* Define gdb::unique_xmalloc_ptr, a gdb::unique_ptr that manages | |
351 | xmalloc'ed memory. */ | |
352 | ||
353 | /* The deleter for gdb::unique_xmalloc_ptr. Uses xfree. */ | |
354 | template <typename T> | |
355 | struct xfree_deleter | |
356 | { | |
357 | void operator() (T *ptr) const { xfree (ptr); } | |
358 | }; | |
359 | ||
360 | #if __cplusplus >= 201103 | |
361 | ||
362 | /* In C++11, we just import the standard unique_ptr to our namespace | |
363 | with a custom deleter. */ | |
364 | ||
365 | template<typename T> using unique_xmalloc_ptr | |
366 | = std::unique_ptr<T, xfree_deleter<T>>; | |
367 | ||
368 | #else /* C++11 */ | |
369 | ||
370 | /* In C++03, we don't have template aliases, so we need to define a | |
371 | subclass instead, and re-define the constructors, because C++03 | |
372 | doesn't support inheriting constructors either. */ | |
373 | ||
374 | template <typename T> | |
375 | class unique_xmalloc_ptr : public unique_ptr<T, xfree_deleter<T> > | |
376 | { | |
377 | typedef unique_ptr<T, xfree_deleter<T> > base_type; | |
378 | ||
379 | DEFINE_GDB_UNIQUE_PTR (unique_xmalloc_ptr) | |
380 | }; | |
381 | ||
382 | #endif /* C++11 */ | |
383 | ||
384 | } /* namespace gdb */ | |
385 | ||
386 | #endif /* GDB_UNIQUE_PTR_H */ |