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.
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
82 #if __cplusplus >= 201103
84 /* In C++11 mode, all we need is import the standard
86 template<typename T
> using unique_ptr
= std::unique_ptr
<T
>;
88 /* Pull in move as well. */
93 /* Default destruction policy used by gnu::unique_ptr when no deleter
94 is specified. Uses delete. */
99 void operator () (T
*ptr
) const { delete ptr
; }
102 /* Specialization for arrays. Uses delete[]. */
105 struct default_delete
<T
[]>
107 void operator () (T
*ptr
) const { delete [] ptr
; }
112 /* Type used to support implicit construction from NULL:
114 gnu::unique_ptr<foo> func (....)
119 and assignment from NULL:
121 gnu::unique_ptr<foo> ptr (....);
125 It is intentionally not defined anywhere. */
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
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 ());
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 ());
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 ()
192 ~unique_ptr_base () { call_deleter (); }
194 /* "explicit operator bool ()" emulation using the safe bool
197 typedef void (unique_ptr_base::*explicit_operator_bool
) () const;
198 void this_type_does_not_support_comparisons () const {}
201 operator explicit_operator_bool () const
203 return (m_ptr
!= NULL
204 ? &unique_ptr_base::this_type_does_not_support_comparisons
208 element_type
*get () const throw () { return m_ptr
; }
210 element_type
*release () throw ()
217 void reset (element_type
*p
= NULL
) throw ()
228 /* Call the deleter. Note we assume the deleter is "stateless". */
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) \
250 explicit TYPE (T *p = NULL) throw () \
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
)
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
)
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
>
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
>
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
>
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
>
318 operator<= (const detail::unique_ptr_base
<T
, D
> &x
,
319 const detail::unique_ptr_base
<U
, E
> &y
)
322 template<typename T
, typename D
,
323 typename U
, typename E
>
325 operator> (const detail::unique_ptr_base
<T
, D
> &x
,
326 const detail::unique_ptr_base
<U
, E
> &y
)
329 template<typename T
, typename D
,
330 typename U
, typename E
>
332 operator>= (const detail::unique_ptr_base
<T
, D
> &x
,
333 const detail::unique_ptr_base
<U
, E
> &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
>
343 move (unique_ptr
<T
, D
> v
)
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
>>;
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
)
401 } /* namespace gnu */
403 #endif /* GNU_UNIQUE_PTR_H */