Add gnu::unique_ptr
[official-gcc.git] / include / unique-ptr.h
blobc5ca031c2842505e8e816a669e7a5c91dd0f7d19
1 /* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
3 Copyright (C) 2007-2016 Free Software Foundation, Inc.
5 This file is part of GCC.
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.
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.
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/>. */
20 /* gnu::unique_ptr defines a C++ owning smart pointer that exposes a
21 subset of the std::unique_ptr API.
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.
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.
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.
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.
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.
54 Usage notes:
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).
60 - Since there's no nullptr in C++03, gnu::unique_ptr allows
61 implicit initialization and assignment from NULL instead.
63 - To check whether there's an associated managed object, all these
64 work as expected:
66 if (ptr)
67 if (!ptr)
68 if (ptr != NULL)
69 if (ptr == NULL)
70 if (NULL != ptr)
71 if (NULL == ptr)
74 #ifndef GNU_UNIQUE_PTR_H
75 #define GNU_UNIQUE_PTR_H 1
77 #include <memory>
79 namespace gnu
82 #if __cplusplus >= 201103
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>;
88 /* Pull in move as well. */
89 using std::move;
91 #else /* C++11 */
93 /* Default destruction policy used by gnu::unique_ptr when no deleter
94 is specified. Uses delete. */
96 template<typename T>
97 struct default_delete
99 void operator () (T *ptr) const { delete ptr; }
102 /* Specialization for arrays. Uses delete[]. */
104 template<typename T>
105 struct default_delete<T[]>
107 void operator () (T *ptr) const { delete [] ptr; }
110 namespace detail
112 /* Type used to support implicit construction from NULL:
114 gnu::unique_ptr<foo> func (....)
116 return NULL;
119 and assignment from NULL:
121 gnu::unique_ptr<foo> ptr (....);
123 ptr = NULL;
125 It is intentionally not defined anywhere. */
126 struct nullptr_t;
128 /* Base class of our unique_ptr emulation. Contains code common to
129 both unique_ptr<T, D> and unique_ptr<T[], D>. */
131 template<typename T, typename D>
132 class unique_ptr_base
134 public:
135 typedef T *pointer;
136 typedef T element_type;
137 typedef D deleter_type;
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) {}
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:
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
151 unique_ptr_base (const unique_ptr_base &other) throw ()
152 : m_ptr (const_cast<unique_ptr_base &> (other).release ()) {}
154 /* Converting "move" constructor. Really an lvalue ref converting
155 constructor that actually moves. This allows constructs such as:
157 unique_ptr<Derived> func_returning_unique_ptr (.....);
159 unique_ptr<Base> ptr = func_returning_unique_ptr (.....);
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 ()) {}
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 ()
169 reset (const_cast<unique_ptr_base &> (other).release ());
170 return *this;
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 ()
178 reset (const_cast<unique_ptr_base<T1, D1> &> (other).release ());
179 return *this;
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;].
186 unique_ptr_base &operator= (detail::nullptr_t *) throw ()
188 reset ();
189 return *this;
192 ~unique_ptr_base () { call_deleter (); }
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 {}
200 public:
201 operator explicit_operator_bool () const
203 return (m_ptr != NULL
204 ? &unique_ptr_base::this_type_does_not_support_comparisons
205 : 0);
208 element_type *get () const throw () { return m_ptr; }
210 element_type *release () throw ()
212 pointer tmp = m_ptr;
213 m_ptr = NULL;
214 return tmp;
217 void reset (element_type *p = NULL) throw ()
219 if (p != m_ptr)
221 call_deleter ();
222 m_ptr = p;
226 private:
228 /* Call the deleter. Note we assume the deleter is "stateless". */
229 void call_deleter ()
231 D d;
233 d (m_ptr);
236 element_type *m_ptr;
239 } /* namespace detail */
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_GNU_UNIQUE_PTR(TYPE) \
249 public: \
250 explicit TYPE (T *p = NULL) throw () \
251 : base_type (p) {} \
253 TYPE (const TYPE &other) throw () : base_type (other) {} \
255 TYPE (detail::nullptr_t *) throw () : base_type (NULL) {} \
257 template<typename T1, typename D1> \
258 TYPE (const detail::unique_ptr_base<T1, D1> &other) throw () \
259 : base_type (other) {} \
261 using base_type::operator=;
263 /* Define single-object gnu::unique_ptr. */
265 template <typename T, typename D = default_delete<T> >
266 class unique_ptr : public detail::unique_ptr_base<T, D>
268 typedef detail::unique_ptr_base<T, D> base_type;
270 DEFINE_GNU_UNIQUE_PTR (unique_ptr)
272 public:
273 /* Dereferencing. */
274 T &operator* () const throw () { return *this->get (); }
275 T *operator-> () const throw () { return this->get (); }
278 /* Define gnu::unique_ptr specialization for T[]. */
280 template <typename T, typename D>
281 class unique_ptr<T[], D> : public detail::unique_ptr_base<T, D>
283 typedef detail::unique_ptr_base<T, D> base_type;
285 DEFINE_GNU_UNIQUE_PTR (unique_ptr)
287 public:
288 /* Indexing operator. */
289 T &operator[] (size_t i) const { return this->get ()[i]; }
292 /* Comparison operators. */
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(); }
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(); }
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 (); }
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); }
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; }
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); }
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 gnu::unique_ptr has move semantics like
339 std::auto_ptr. I.e., copy/assignment actually moves. */
341 template<typename T, typename D>
342 unique_ptr<T, D>
343 move (unique_ptr<T, D> v)
345 return v;
348 #endif /* C++11 */
350 /* Define gnu::unique_xmalloc_ptr, a gnu::unique_ptr that manages
351 xmalloc'ed memory. */
353 /* The deleter for gnu::unique_xmalloc_ptr. Uses free. */
354 template <typename T>
355 struct xmalloc_deleter
357 void operator() (T *ptr) const { free (ptr); }
360 /* Same, for arrays. */
361 template <typename T>
362 struct xmalloc_deleter<T[]>
364 void operator() (T *ptr) const { free (ptr); }
367 #if __cplusplus >= 201103
369 /* In C++11, we just import the standard unique_ptr to our namespace
370 with a custom deleter. */
372 template<typename T> using unique_xmalloc_ptr
373 = std::unique_ptr<T, xmalloc_deleter<T>>;
375 #else /* C++11 */
377 /* In C++03, we don't have template aliases, so we need to define a
378 subclass instead, and re-define the constructors, because C++03
379 doesn't support inheriting constructors either. */
381 template <typename T>
382 class unique_xmalloc_ptr : public unique_ptr<T, xmalloc_deleter<T> >
384 typedef unique_ptr<T, xmalloc_deleter<T> > base_type;
386 DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
389 /* Define gnu::unique_xmalloc_ptr specialization for T[]. */
391 template <typename T>
392 class unique_xmalloc_ptr<T[]> : public unique_ptr<T[], xmalloc_deleter<T[]> >
394 typedef unique_ptr<T[], xmalloc_deleter<T[]> > base_type;
396 DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
399 #endif /* C++11 */
401 } /* namespace gnu */
403 #endif /* GNU_UNIQUE_PTR_H */