1 /* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
3 Copyright (C) 2007-2019 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.
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
74 #ifndef GNU_UNIQUE_PTR_H
75 #define GNU_UNIQUE_PTR_H 1
77 #if __cplusplus >= 201103
84 #if __cplusplus >= 201103
86 /* In C++11 mode, all we need is import the standard
88 template<typename T
> using unique_ptr
= std::unique_ptr
<T
>;
90 /* Pull in move as well. */
95 /* Default destruction policy used by gnu::unique_ptr when no deleter
96 is specified. Uses delete. */
101 void operator () (T
*ptr
) const { delete ptr
; }
104 /* Specialization for arrays. Uses delete[]. */
107 struct default_delete
<T
[]>
109 void operator () (T
*ptr
) const { delete [] ptr
; }
114 /* Type used to support implicit construction from NULL:
116 gnu::unique_ptr<foo> func (....)
121 and assignment from NULL:
123 gnu::unique_ptr<foo> ptr (....);
127 It is intentionally not defined anywhere. */
130 /* Base class of our unique_ptr emulation. Contains code common to
131 both unique_ptr<T, D> and unique_ptr<T[], D>. */
133 template<typename T
, typename D
>
134 class unique_ptr_base
138 typedef T element_type
;
139 typedef D deleter_type
;
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
) {}
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:
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
153 unique_ptr_base (const unique_ptr_base
&other
) throw ()
154 : m_ptr (const_cast<unique_ptr_base
&> (other
).release ()) {}
156 /* Converting "move" constructor. Really an lvalue ref converting
157 constructor that actually moves. This allows constructs such as:
159 unique_ptr<Derived> func_returning_unique_ptr (.....);
161 unique_ptr<Base> ptr = func_returning_unique_ptr (.....);
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 ()) {}
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 ()
171 reset (const_cast<unique_ptr_base
&> (other
).release ());
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 ()
180 reset (const_cast<unique_ptr_base
<T1
, D1
> &> (other
).release ());
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;].
188 unique_ptr_base
&operator= (detail::nullptr_t
*) throw ()
194 ~unique_ptr_base () { call_deleter (); }
196 /* "explicit operator bool ()" emulation using the safe bool
199 typedef void (unique_ptr_base::*explicit_operator_bool
) () const;
200 void this_type_does_not_support_comparisons () const {}
203 operator explicit_operator_bool () const
205 return (m_ptr
!= NULL
206 ? &unique_ptr_base::this_type_does_not_support_comparisons
210 element_type
*get () const throw () { return m_ptr
; }
212 element_type
*release () throw ()
219 void reset (element_type
*p
= NULL
) throw ()
230 /* Call the deleter. Note we assume the deleter is "stateless". */
241 } /* namespace detail */
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) \
252 explicit TYPE (T *p = NULL) throw () \
255 TYPE (const TYPE &other) throw () : base_type (other) {} \
257 TYPE (detail::nullptr_t *) throw () : base_type (NULL) {} \
259 template<typename T1, typename D1> \
260 TYPE (const detail::unique_ptr_base<T1, D1> &other) throw () \
261 : base_type (other) {} \
263 using base_type::operator=;
265 /* Define single-object gnu::unique_ptr. */
267 template <typename T
, typename D
= default_delete
<T
> >
268 class unique_ptr
: public detail::unique_ptr_base
<T
, D
>
270 typedef detail::unique_ptr_base
<T
, D
> base_type
;
272 DEFINE_GNU_UNIQUE_PTR (unique_ptr
)
276 T
&operator* () const throw () { return *this->get (); }
277 T
*operator-> () const throw () { return this->get (); }
280 /* Define gnu::unique_ptr specialization for T[]. */
282 template <typename T
, typename D
>
283 class unique_ptr
<T
[], D
> : public detail::unique_ptr_base
<T
, D
>
285 typedef detail::unique_ptr_base
<T
, D
> base_type
;
287 DEFINE_GNU_UNIQUE_PTR (unique_ptr
)
290 /* Indexing operator. */
291 T
&operator[] (size_t i
) const { return this->get ()[i
]; }
294 /* Comparison operators. */
296 template <typename T
, typename D
,
297 typename U
, typename E
>
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(); }
303 template <typename T
, typename D
,
304 typename U
, typename E
>
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(); }
310 template<typename T
, typename D
,
311 typename U
, typename E
>
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 (); }
317 template<typename T
, typename D
,
318 typename U
, typename E
>
320 operator<= (const detail::unique_ptr_base
<T
, D
> &x
,
321 const detail::unique_ptr_base
<U
, E
> &y
)
324 template<typename T
, typename D
,
325 typename U
, typename E
>
327 operator> (const detail::unique_ptr_base
<T
, D
> &x
,
328 const detail::unique_ptr_base
<U
, E
> &y
)
331 template<typename T
, typename D
,
332 typename U
, typename E
>
334 operator>= (const detail::unique_ptr_base
<T
, D
> &x
,
335 const detail::unique_ptr_base
<U
, E
> &y
)
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. */
352 /* Define gnu::unique_xmalloc_ptr, a gnu::unique_ptr that manages
353 xmalloc'ed memory. */
355 /* The deleter for gnu::unique_xmalloc_ptr. Uses free. */
356 template <typename T
>
357 struct xmalloc_deleter
359 void operator() (T
*ptr
) const { free (ptr
); }
362 /* Same, for arrays. */
363 template <typename T
>
364 struct xmalloc_deleter
<T
[]>
366 void operator() (T
*ptr
) const { free (ptr
); }
369 #if __cplusplus >= 201103
371 /* In C++11, we just import the standard unique_ptr to our namespace
372 with a custom deleter. */
374 template<typename T
> using unique_xmalloc_ptr
375 = std::unique_ptr
<T
, xmalloc_deleter
<T
>>;
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. */
383 template <typename T
>
384 class unique_xmalloc_ptr
: public unique_ptr
<T
, xmalloc_deleter
<T
> >
386 typedef unique_ptr
<T
, xmalloc_deleter
<T
> > base_type
;
388 DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr
)
391 /* Define gnu::unique_xmalloc_ptr specialization for T[]. */
393 template <typename T
>
394 class unique_xmalloc_ptr
<T
[]> : public unique_ptr
<T
[], xmalloc_deleter
<T
[]> >
396 typedef unique_ptr
<T
[], xmalloc_deleter
<T
[]> > base_type
;
398 DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr
)
403 } /* namespace gnu */
405 #endif /* GNU_UNIQUE_PTR_H */