]> git.ipfire.org Git - thirdparty/gcc.git/blob - include/unique-ptr.h
Add one target hook predict_doloop_p, it return true if we can predict it
[thirdparty/gcc.git] / include / unique-ptr.h
1 /* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
2
3 Copyright (C) 2007-2019 Free Software Foundation, Inc.
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
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. */
342
343 template<typename T>
344 const T&
345 move (T& 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 */