xref: /dflybsd-src/contrib/gcc-8.0/include/unique-ptr.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
2*38fd1498Szrj 
3*38fd1498Szrj    Copyright (C) 2007-2018 Free Software Foundation, Inc.
4*38fd1498Szrj 
5*38fd1498Szrj    This file is part of GCC.
6*38fd1498Szrj 
7*38fd1498Szrj    This program is free software; you can redistribute it and/or modify
8*38fd1498Szrj    it under the terms of the GNU General Public License as published by
9*38fd1498Szrj    the Free Software Foundation; either version 3 of the License, or
10*38fd1498Szrj    (at your option) any later version.
11*38fd1498Szrj 
12*38fd1498Szrj    This program is distributed in the hope that it will be useful,
13*38fd1498Szrj    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*38fd1498Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*38fd1498Szrj    GNU General Public License for more details.
16*38fd1498Szrj 
17*38fd1498Szrj    You should have received a copy of the GNU General Public License
18*38fd1498Szrj    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj /* gnu::unique_ptr defines a C++ owning smart pointer that exposes a
21*38fd1498Szrj    subset of the std::unique_ptr API.
22*38fd1498Szrj 
23*38fd1498Szrj    In fact, when compiled with a C++11 compiler, gnu::unique_ptr
24*38fd1498Szrj    actually _is_ std::unique_ptr.  When compiled with a C++03 compiler
25*38fd1498Szrj    OTOH, it's an hand coded std::unique_ptr emulation that assumes
26*38fd1498Szrj    code is correct and doesn't try to be too smart.
27*38fd1498Szrj 
28*38fd1498Szrj    This supports custom deleters, but not _stateful_ deleters, so you
29*38fd1498Szrj    can't use those in C++11 mode either.  Only the managed pointer is
30*38fd1498Szrj    stored in the smart pointer.  That could be changed; it simply
31*38fd1498Szrj    wasn't found necessary.
32*38fd1498Szrj 
33*38fd1498Szrj    At the end of the file you'll find a gnu::unique_ptr partial
34*38fd1498Szrj    specialization that uses a custom (stateless) deleter:
35*38fd1498Szrj    gnu::unique_xmalloc_ptr.  That is used to manage pointers to
36*38fd1498Szrj    objects allocated with xmalloc.
37*38fd1498Szrj 
38*38fd1498Szrj    The C++03 version was originally based on GCC 7.0's std::auto_ptr
39*38fd1498Szrj    and then heavily customized to behave more like C++11's
40*38fd1498Szrj    std::unique_ptr, but at this point, it no longer shares much at all
41*38fd1498Szrj    with the original file.  But, that's the history and the reason for
42*38fd1498Szrj    the copyright's starting year.
43*38fd1498Szrj 
44*38fd1498Szrj    The C++03 version lets you shoot yourself in the foot, since
45*38fd1498Szrj    similarly to std::auto_ptr, the copy constructor and assignment
46*38fd1498Szrj    operators actually move.  Also, in the name of simplicity, no
47*38fd1498Szrj    effort is spent on using SFINAE to prevent invalid conversions,
48*38fd1498Szrj    etc.  This is not really a problem, because the goal here is to
49*38fd1498Szrj    allow code that would be correct using std::unique_ptr to be
50*38fd1498Szrj    equally correct in C++03 mode, and, just as efficient.  If client
51*38fd1498Szrj    code compiles correctly with a C++11 (or newer) compiler, we know
52*38fd1498Szrj    we're not doing anything invalid by mistake.
53*38fd1498Szrj 
54*38fd1498Szrj    Usage notes:
55*38fd1498Szrj 
56*38fd1498Szrj    - Putting gnu::unique_ptr in standard containers is not supported,
57*38fd1498Szrj      since C++03 containers are not move-aware (and our emulation
58*38fd1498Szrj      relies on copy actually moving).
59*38fd1498Szrj 
60*38fd1498Szrj    - Since there's no nullptr in C++03, gnu::unique_ptr allows
61*38fd1498Szrj      implicit initialization and assignment from NULL instead.
62*38fd1498Szrj 
63*38fd1498Szrj    - To check whether there's an associated managed object, all these
64*38fd1498Szrj      work as expected:
65*38fd1498Szrj 
66*38fd1498Szrj       if (ptr)
67*38fd1498Szrj       if (!ptr)
68*38fd1498Szrj       if (ptr != NULL)
69*38fd1498Szrj       if (ptr == NULL)
70*38fd1498Szrj       if (NULL != ptr)
71*38fd1498Szrj       if (NULL == ptr)
72*38fd1498Szrj */
73*38fd1498Szrj 
74*38fd1498Szrj #ifndef GNU_UNIQUE_PTR_H
75*38fd1498Szrj #define GNU_UNIQUE_PTR_H 1
76*38fd1498Szrj 
77*38fd1498Szrj #if __cplusplus >= 201103
78*38fd1498Szrj # include <memory>
79*38fd1498Szrj #endif
80*38fd1498Szrj 
81*38fd1498Szrj namespace gnu
82*38fd1498Szrj {
83*38fd1498Szrj 
84*38fd1498Szrj #if __cplusplus >= 201103
85*38fd1498Szrj 
86*38fd1498Szrj /* In C++11 mode, all we need is import the standard
87*38fd1498Szrj    std::unique_ptr.  */
88*38fd1498Szrj template<typename T> using unique_ptr = std::unique_ptr<T>;
89*38fd1498Szrj 
90*38fd1498Szrj /* Pull in move as well.  */
91*38fd1498Szrj using std::move;
92*38fd1498Szrj 
93*38fd1498Szrj #else /* C++11 */
94*38fd1498Szrj 
95*38fd1498Szrj /* Default destruction policy used by gnu::unique_ptr when no deleter
96*38fd1498Szrj    is specified.  Uses delete.  */
97*38fd1498Szrj 
98*38fd1498Szrj template<typename T>
99*38fd1498Szrj struct default_delete
100*38fd1498Szrj {
101*38fd1498Szrj   void operator () (T *ptr) const { delete ptr; }
102*38fd1498Szrj };
103*38fd1498Szrj 
104*38fd1498Szrj /* Specialization for arrays.  Uses delete[].  */
105*38fd1498Szrj 
106*38fd1498Szrj template<typename T>
107*38fd1498Szrj struct default_delete<T[]>
108*38fd1498Szrj {
109*38fd1498Szrj   void operator () (T *ptr) const { delete [] ptr; }
110*38fd1498Szrj };
111*38fd1498Szrj 
112*38fd1498Szrj namespace detail
113*38fd1498Szrj {
114*38fd1498Szrj /* Type used to support implicit construction from NULL:
115*38fd1498Szrj 
116*38fd1498Szrj      gnu::unique_ptr<foo> func (....)
117*38fd1498Szrj      {
118*38fd1498Szrj      return NULL;
119*38fd1498Szrj      }
120*38fd1498Szrj 
121*38fd1498Szrj    and assignment from NULL:
122*38fd1498Szrj 
123*38fd1498Szrj      gnu::unique_ptr<foo> ptr (....);
124*38fd1498Szrj      ...
125*38fd1498Szrj      ptr = NULL;
126*38fd1498Szrj 
127*38fd1498Szrj   It is intentionally not defined anywhere.  */
128*38fd1498Szrj struct nullptr_t;
129*38fd1498Szrj 
130*38fd1498Szrj /* Base class of our unique_ptr emulation.  Contains code common to
131*38fd1498Szrj    both unique_ptr<T, D> and unique_ptr<T[], D>.  */
132*38fd1498Szrj 
133*38fd1498Szrj template<typename T, typename D>
134*38fd1498Szrj class unique_ptr_base
135*38fd1498Szrj {
136*38fd1498Szrj public:
137*38fd1498Szrj   typedef T *pointer;
138*38fd1498Szrj   typedef T element_type;
139*38fd1498Szrj   typedef D deleter_type;
140*38fd1498Szrj 
141*38fd1498Szrj   /* Takes ownership of a pointer.  P is a pointer to an object of
142*38fd1498Szrj      element_type type.  Defaults to NULL.  */
143*38fd1498Szrj   explicit unique_ptr_base (element_type *p = NULL) throw () : m_ptr (p) {}
144*38fd1498Szrj 
145*38fd1498Szrj   /* The "move" constructor.  Really a copy constructor that actually
146*38fd1498Szrj      moves.  Even though std::unique_ptr is not copyable, our little
147*38fd1498Szrj      simpler emulation allows it, because:
148*38fd1498Szrj 
149*38fd1498Szrj        - There are no rvalue references in C++03.  Our move emulation
150*38fd1498Szrj        instead relies on copy/assignment moving, like std::auto_ptr.
151*38fd1498Szrj        - RVO/NRVO requires an accessible copy constructor
152*38fd1498Szrj   */
153*38fd1498Szrj   unique_ptr_base (const unique_ptr_base &other) throw ()
154*38fd1498Szrj     : m_ptr (const_cast<unique_ptr_base &> (other).release ()) {}
155*38fd1498Szrj 
156*38fd1498Szrj   /* Converting "move" constructor.  Really an lvalue ref converting
157*38fd1498Szrj      constructor that actually moves.  This allows constructs such as:
158*38fd1498Szrj 
159*38fd1498Szrj       unique_ptr<Derived> func_returning_unique_ptr (.....);
160*38fd1498Szrj       ...
161*38fd1498Szrj       unique_ptr<Base> ptr = func_returning_unique_ptr (.....);
162*38fd1498Szrj   */
163*38fd1498Szrj   template<typename T1, typename D1>
164*38fd1498Szrj   unique_ptr_base (const unique_ptr_base<T1, D1> &other) throw ()
165*38fd1498Szrj     : m_ptr (const_cast<unique_ptr_base<T1, D1> &> (other).release ()) {}
166*38fd1498Szrj 
167*38fd1498Szrj   /* The "move" assignment operator.  Really an lvalue ref copy
168*38fd1498Szrj      assignment operator that actually moves.  See comments above.  */
169*38fd1498Szrj   unique_ptr_base &operator= (const unique_ptr_base &other) throw ()
170*38fd1498Szrj   {
171*38fd1498Szrj     reset (const_cast<unique_ptr_base &> (other).release ());
172*38fd1498Szrj     return *this;
173*38fd1498Szrj   }
174*38fd1498Szrj 
175*38fd1498Szrj   /* Converting "move" assignment.  Really an lvalue ref converting
176*38fd1498Szrj      copy assignment operator that moves.  See comments above.  */
177*38fd1498Szrj   template<typename T1, typename D1>
178*38fd1498Szrj   unique_ptr_base &operator= (const unique_ptr_base<T1, D1> &other) throw ()
179*38fd1498Szrj   {
180*38fd1498Szrj     reset (const_cast<unique_ptr_base<T1, D1> &> (other).release ());
181*38fd1498Szrj     return *this;
182*38fd1498Szrj   }
183*38fd1498Szrj 
184*38fd1498Szrj   /* std::unique_ptr does not allow assignment, except from nullptr.
185*38fd1498Szrj      nullptr doesn't exist in C++03, so we allow assignment from NULL
186*38fd1498Szrj      instead [ptr = NULL;].
187*38fd1498Szrj   */
188*38fd1498Szrj   unique_ptr_base &operator= (detail::nullptr_t *) throw ()
189*38fd1498Szrj   {
190*38fd1498Szrj     reset ();
191*38fd1498Szrj     return *this;
192*38fd1498Szrj   }
193*38fd1498Szrj 
194*38fd1498Szrj   ~unique_ptr_base () { call_deleter (); }
195*38fd1498Szrj 
196*38fd1498Szrj   /* "explicit operator bool ()" emulation using the safe bool
197*38fd1498Szrj      idiom.  */
198*38fd1498Szrj private:
199*38fd1498Szrj   typedef void (unique_ptr_base::*explicit_operator_bool) () const;
200*38fd1498Szrj   void this_type_does_not_support_comparisons () const {}
201*38fd1498Szrj 
202*38fd1498Szrj public:
203*38fd1498Szrj   operator explicit_operator_bool () const
204*38fd1498Szrj   {
205*38fd1498Szrj     return (m_ptr != NULL
206*38fd1498Szrj 	    ? &unique_ptr_base::this_type_does_not_support_comparisons
207*38fd1498Szrj 	    : 0);
208*38fd1498Szrj   }
209*38fd1498Szrj 
210*38fd1498Szrj   element_type *get () const throw () { return m_ptr; }
211*38fd1498Szrj 
212*38fd1498Szrj   element_type *release () throw ()
213*38fd1498Szrj   {
214*38fd1498Szrj     pointer tmp = m_ptr;
215*38fd1498Szrj     m_ptr = NULL;
216*38fd1498Szrj     return tmp;
217*38fd1498Szrj   }
218*38fd1498Szrj 
219*38fd1498Szrj   void reset (element_type *p = NULL) throw ()
220*38fd1498Szrj   {
221*38fd1498Szrj     if (p != m_ptr)
222*38fd1498Szrj       {
223*38fd1498Szrj 	call_deleter ();
224*38fd1498Szrj 	m_ptr = p;
225*38fd1498Szrj       }
226*38fd1498Szrj   }
227*38fd1498Szrj 
228*38fd1498Szrj private:
229*38fd1498Szrj 
230*38fd1498Szrj   /* Call the deleter.  Note we assume the deleter is "stateless".  */
231*38fd1498Szrj   void call_deleter ()
232*38fd1498Szrj   {
233*38fd1498Szrj     D d;
234*38fd1498Szrj 
235*38fd1498Szrj     d (m_ptr);
236*38fd1498Szrj   }
237*38fd1498Szrj 
238*38fd1498Szrj   element_type *m_ptr;
239*38fd1498Szrj };
240*38fd1498Szrj 
241*38fd1498Szrj } /* namespace detail */
242*38fd1498Szrj 
243*38fd1498Szrj /* Macro used to create a unique_ptr_base "partial specialization" --
244*38fd1498Szrj    a subclass that uses a specific deleter.  Basically this re-defines
245*38fd1498Szrj    the necessary constructors.  This is necessary because C++03
246*38fd1498Szrj    doesn't support inheriting constructors with "using".  While at it,
247*38fd1498Szrj    we inherit the assignment operator.  TYPE is the name of the type
248*38fd1498Szrj    being defined.  Assumes that 'base_type' is a typedef of the
249*38fd1498Szrj    baseclass TYPE is inheriting from.  */
250*38fd1498Szrj #define DEFINE_GNU_UNIQUE_PTR(TYPE)						\
251*38fd1498Szrj public:									\
252*38fd1498Szrj   explicit TYPE (T *p = NULL) throw ()					\
253*38fd1498Szrj     : base_type (p) {}							\
254*38fd1498Szrj 									\
255*38fd1498Szrj   TYPE (const TYPE &other) throw () : base_type (other) {}		\
256*38fd1498Szrj 									\
257*38fd1498Szrj   TYPE (detail::nullptr_t *) throw () : base_type (NULL) {}		\
258*38fd1498Szrj 									\
259*38fd1498Szrj   template<typename T1, typename D1>					\
260*38fd1498Szrj   TYPE (const detail::unique_ptr_base<T1, D1> &other) throw ()		\
261*38fd1498Szrj     : base_type (other) {}						\
262*38fd1498Szrj 									\
263*38fd1498Szrj   using base_type::operator=;
264*38fd1498Szrj 
265*38fd1498Szrj /* Define single-object gnu::unique_ptr.  */
266*38fd1498Szrj 
267*38fd1498Szrj template <typename T, typename D = default_delete<T> >
268*38fd1498Szrj class unique_ptr : public detail::unique_ptr_base<T, D>
269*38fd1498Szrj {
270*38fd1498Szrj   typedef detail::unique_ptr_base<T, D> base_type;
271*38fd1498Szrj 
272*38fd1498Szrj   DEFINE_GNU_UNIQUE_PTR (unique_ptr)
273*38fd1498Szrj 
274*38fd1498Szrj public:
275*38fd1498Szrj   /* Dereferencing.  */
276*38fd1498Szrj   T &operator* () const throw () { return *this->get (); }
277*38fd1498Szrj   T *operator-> () const throw () { return this->get (); }
278*38fd1498Szrj };
279*38fd1498Szrj 
280*38fd1498Szrj /* Define gnu::unique_ptr specialization for T[].  */
281*38fd1498Szrj 
282*38fd1498Szrj template <typename T, typename D>
283*38fd1498Szrj class unique_ptr<T[], D> : public detail::unique_ptr_base<T, D>
284*38fd1498Szrj {
285*38fd1498Szrj   typedef detail::unique_ptr_base<T, D> base_type;
286*38fd1498Szrj 
287*38fd1498Szrj   DEFINE_GNU_UNIQUE_PTR (unique_ptr)
288*38fd1498Szrj 
289*38fd1498Szrj public:
290*38fd1498Szrj   /* Indexing operator.  */
291*38fd1498Szrj   T &operator[] (size_t i) const { return this->get ()[i]; }
292*38fd1498Szrj };
293*38fd1498Szrj 
294*38fd1498Szrj /* Comparison operators.  */
295*38fd1498Szrj 
296*38fd1498Szrj template <typename T, typename D,
297*38fd1498Szrj 	  typename U, typename E>
298*38fd1498Szrj inline bool
299*38fd1498Szrj operator== (const detail::unique_ptr_base<T, D> &x,
300*38fd1498Szrj 	    const detail::unique_ptr_base<U, E> &y)
301*38fd1498Szrj { return x.get() == y.get(); }
302*38fd1498Szrj 
303*38fd1498Szrj template <typename T, typename D,
304*38fd1498Szrj 	  typename U, typename E>
305*38fd1498Szrj inline bool
306*38fd1498Szrj operator!= (const detail::unique_ptr_base<T, D> &x,
307*38fd1498Szrj 	    const detail::unique_ptr_base<U, E> &y)
308*38fd1498Szrj { return x.get() != y.get(); }
309*38fd1498Szrj 
310*38fd1498Szrj template<typename T, typename D,
311*38fd1498Szrj 	 typename U, typename E>
312*38fd1498Szrj inline bool
313*38fd1498Szrj operator< (const detail::unique_ptr_base<T, D> &x,
314*38fd1498Szrj 	   const detail::unique_ptr_base<U, E> &y)
315*38fd1498Szrj { return x.get() < y.get (); }
316*38fd1498Szrj 
317*38fd1498Szrj template<typename T, typename D,
318*38fd1498Szrj 	 typename U, typename E>
319*38fd1498Szrj inline bool
320*38fd1498Szrj operator<= (const detail::unique_ptr_base<T, D> &x,
321*38fd1498Szrj 	    const detail::unique_ptr_base<U, E> &y)
322*38fd1498Szrj { return !(y < x); }
323*38fd1498Szrj 
324*38fd1498Szrj template<typename T, typename D,
325*38fd1498Szrj 	 typename U, typename E>
326*38fd1498Szrj inline bool
327*38fd1498Szrj operator> (const detail::unique_ptr_base<T, D> &x,
328*38fd1498Szrj 	   const detail::unique_ptr_base<U, E> &y)
329*38fd1498Szrj { return y < x; }
330*38fd1498Szrj 
331*38fd1498Szrj template<typename T, typename D,
332*38fd1498Szrj 	 typename U, typename E>
333*38fd1498Szrj inline bool
334*38fd1498Szrj operator>= (const detail::unique_ptr_base<T, D> &x,
335*38fd1498Szrj 	    const detail::unique_ptr_base<U, E> &y)
336*38fd1498Szrj { return !(x < y); }
337*38fd1498Szrj 
338*38fd1498Szrj /* std::move "emulation".  This is as simple as it can be -- no
339*38fd1498Szrj    attempt is made to emulate rvalue references.  Instead relies on
340*38fd1498Szrj    the fact that gnu::unique_ptr has move semantics like
341*38fd1498Szrj    std::auto_ptr.  I.e., copy/assignment actually moves.  */
342*38fd1498Szrj 
343*38fd1498Szrj template<typename T, typename D>
344*38fd1498Szrj unique_ptr<T, D>
345*38fd1498Szrj move (unique_ptr<T, D> v)
346*38fd1498Szrj {
347*38fd1498Szrj   return v;
348*38fd1498Szrj }
349*38fd1498Szrj 
350*38fd1498Szrj #endif /* C++11 */
351*38fd1498Szrj 
352*38fd1498Szrj /* Define gnu::unique_xmalloc_ptr, a gnu::unique_ptr that manages
353*38fd1498Szrj    xmalloc'ed memory.  */
354*38fd1498Szrj 
355*38fd1498Szrj /* The deleter for gnu::unique_xmalloc_ptr.  Uses free.  */
356*38fd1498Szrj template <typename T>
357*38fd1498Szrj struct xmalloc_deleter
358*38fd1498Szrj {
operatorxmalloc_deleter359*38fd1498Szrj   void operator() (T *ptr) const { free (ptr); }
360*38fd1498Szrj };
361*38fd1498Szrj 
362*38fd1498Szrj /* Same, for arrays.  */
363*38fd1498Szrj template <typename T>
364*38fd1498Szrj struct xmalloc_deleter<T[]>
365*38fd1498Szrj {
366*38fd1498Szrj   void operator() (T *ptr) const { free (ptr); }
367*38fd1498Szrj };
368*38fd1498Szrj 
369*38fd1498Szrj #if __cplusplus >= 201103
370*38fd1498Szrj 
371*38fd1498Szrj /* In C++11, we just import the standard unique_ptr to our namespace
372*38fd1498Szrj    with a custom deleter.  */
373*38fd1498Szrj 
374*38fd1498Szrj template<typename T> using unique_xmalloc_ptr
375*38fd1498Szrj   = std::unique_ptr<T, xmalloc_deleter<T>>;
376*38fd1498Szrj 
377*38fd1498Szrj #else /* C++11 */
378*38fd1498Szrj 
379*38fd1498Szrj /* In C++03, we don't have template aliases, so we need to define a
380*38fd1498Szrj    subclass instead, and re-define the constructors, because C++03
381*38fd1498Szrj    doesn't support inheriting constructors either.  */
382*38fd1498Szrj 
383*38fd1498Szrj template <typename T>
384*38fd1498Szrj class unique_xmalloc_ptr : public unique_ptr<T, xmalloc_deleter<T> >
385*38fd1498Szrj {
386*38fd1498Szrj   typedef unique_ptr<T, xmalloc_deleter<T> > base_type;
387*38fd1498Szrj 
388*38fd1498Szrj   DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
389*38fd1498Szrj };
390*38fd1498Szrj 
391*38fd1498Szrj /* Define gnu::unique_xmalloc_ptr specialization for T[].  */
392*38fd1498Szrj 
393*38fd1498Szrj template <typename T>
394*38fd1498Szrj class unique_xmalloc_ptr<T[]> : public unique_ptr<T[], xmalloc_deleter<T[]> >
395*38fd1498Szrj {
396*38fd1498Szrj   typedef unique_ptr<T[], xmalloc_deleter<T[]> > base_type;
397*38fd1498Szrj 
398*38fd1498Szrj   DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
399*38fd1498Szrj };
400*38fd1498Szrj 
401*38fd1498Szrj #endif /* C++11 */
402*38fd1498Szrj 
403*38fd1498Szrj } /* namespace gnu */
404*38fd1498Szrj 
405*38fd1498Szrj #endif /* GNU_UNIQUE_PTR_H */
406