mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			406 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			406 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
| /* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
 | |
| 
 | |
|    Copyright (C) 2007-2019 Free Software Foundation, Inc.
 | |
| 
 | |
|    This file is part of GCC.
 | |
| 
 | |
|    This program is free software; you can redistribute it and/or modify
 | |
|    it under the terms of the GNU General Public License as published by
 | |
|    the Free Software Foundation; either version 3 of the License, or
 | |
|    (at your option) any later version.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|    GNU General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License
 | |
|    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 | |
| 
 | |
| /* gnu::unique_ptr defines a C++ owning smart pointer that exposes a
 | |
|    subset of the std::unique_ptr API.
 | |
| 
 | |
|    In fact, when compiled with a C++11 compiler, gnu::unique_ptr
 | |
|    actually _is_ std::unique_ptr.  When compiled with a C++03 compiler
 | |
|    OTOH, it's an hand coded std::unique_ptr emulation that assumes
 | |
|    code is correct and doesn't try to be too smart.
 | |
| 
 | |
|    This supports custom deleters, but not _stateful_ deleters, so you
 | |
|    can't use those in C++11 mode either.  Only the managed pointer is
 | |
|    stored in the smart pointer.  That could be changed; it simply
 | |
|    wasn't found necessary.
 | |
| 
 | |
|    At the end of the file you'll find a gnu::unique_ptr partial
 | |
|    specialization that uses a custom (stateless) deleter:
 | |
|    gnu::unique_xmalloc_ptr.  That is used to manage pointers to
 | |
|    objects allocated with xmalloc.
 | |
| 
 | |
|    The C++03 version was originally based on GCC 7.0's std::auto_ptr
 | |
|    and then heavily customized to behave more like C++11's
 | |
|    std::unique_ptr, but at this point, it no longer shares much at all
 | |
|    with the original file.  But, that's the history and the reason for
 | |
|    the copyright's starting year.
 | |
| 
 | |
|    The C++03 version lets you shoot yourself in the foot, since
 | |
|    similarly to std::auto_ptr, the copy constructor and assignment
 | |
|    operators actually move.  Also, in the name of simplicity, no
 | |
|    effort is spent on using SFINAE to prevent invalid conversions,
 | |
|    etc.  This is not really a problem, because the goal here is to
 | |
|    allow code that would be correct using std::unique_ptr to be
 | |
|    equally correct in C++03 mode, and, just as efficient.  If client
 | |
|    code compiles correctly with a C++11 (or newer) compiler, we know
 | |
|    we're not doing anything invalid by mistake.
 | |
| 
 | |
|    Usage notes:
 | |
| 
 | |
|    - Putting gnu::unique_ptr in standard containers is not supported,
 | |
|      since C++03 containers are not move-aware (and our emulation
 | |
|      relies on copy actually moving).
 | |
| 
 | |
|    - Since there's no nullptr in C++03, gnu::unique_ptr allows
 | |
|      implicit initialization and assignment from NULL instead.
 | |
| 
 | |
|    - To check whether there's an associated managed object, all these
 | |
|      work as expected:
 | |
| 
 | |
|       if (ptr)
 | |
|       if (!ptr)
 | |
|       if (ptr != NULL)
 | |
|       if (ptr == NULL)
 | |
|       if (NULL != ptr)
 | |
|       if (NULL == ptr)
 | |
| */
 | |
| 
 | |
| #ifndef GNU_UNIQUE_PTR_H
 | |
| #define GNU_UNIQUE_PTR_H 1
 | |
| 
 | |
| #if __cplusplus >= 201103
 | |
| # include <memory>
 | |
| #endif
 | |
| 
 | |
| namespace gnu
 | |
| {
 | |
| 
 | |
| #if __cplusplus >= 201103
 | |
| 
 | |
| /* In C++11 mode, all we need is import the standard
 | |
|    std::unique_ptr.  */
 | |
| template<typename T> using unique_ptr = std::unique_ptr<T>;
 | |
| 
 | |
| /* Pull in move as well.  */
 | |
| using std::move;
 | |
| 
 | |
| #else /* C++11 */
 | |
| 
 | |
| /* Default destruction policy used by gnu::unique_ptr when no deleter
 | |
|    is specified.  Uses delete.  */
 | |
| 
 | |
| template<typename T>
 | |
| struct default_delete
 | |
| {
 | |
|   void operator () (T *ptr) const { delete ptr; }
 | |
| };
 | |
| 
 | |
| /* Specialization for arrays.  Uses delete[].  */
 | |
| 
 | |
| template<typename T>
 | |
| struct default_delete<T[]>
 | |
| {
 | |
|   void operator () (T *ptr) const { delete [] ptr; }
 | |
| };
 | |
| 
 | |
| namespace detail
 | |
| {
 | |
| /* Type used to support implicit construction from NULL:
 | |
| 
 | |
|      gnu::unique_ptr<foo> func (....)
 | |
|      {
 | |
|      return NULL;
 | |
|      }
 | |
| 
 | |
|    and assignment from NULL:
 | |
| 
 | |
|      gnu::unique_ptr<foo> ptr (....);
 | |
|      ...
 | |
|      ptr = NULL;
 | |
| 
 | |
|   It is intentionally not defined anywhere.  */
 | |
| struct nullptr_t;
 | |
| 
 | |
| /* Base class of our unique_ptr emulation.  Contains code common to
 | |
|    both unique_ptr<T, D> and unique_ptr<T[], D>.  */
 | |
| 
 | |
| template<typename T, typename D>
 | |
| class unique_ptr_base
 | |
| {
 | |
| public:
 | |
|   typedef T *pointer;
 | |
|   typedef T element_type;
 | |
|   typedef D deleter_type;
 | |
| 
 | |
|   /* Takes ownership of a pointer.  P is a pointer to an object of
 | |
|      element_type type.  Defaults to NULL.  */
 | |
|   explicit unique_ptr_base (element_type *p = NULL) throw () : m_ptr (p) {}
 | |
| 
 | |
|   /* The "move" constructor.  Really a copy constructor that actually
 | |
|      moves.  Even though std::unique_ptr is not copyable, our little
 | |
|      simpler emulation allows it, because:
 | |
| 
 | |
|        - There are no rvalue references in C++03.  Our move emulation
 | |
|        instead relies on copy/assignment moving, like std::auto_ptr.
 | |
|        - RVO/NRVO requires an accessible copy constructor
 | |
|   */
 | |
|   unique_ptr_base (const unique_ptr_base &other) throw ()
 | |
|     : m_ptr (const_cast<unique_ptr_base &> (other).release ()) {}
 | |
| 
 | |
|   /* Converting "move" constructor.  Really an lvalue ref converting
 | |
|      constructor that actually moves.  This allows constructs such as:
 | |
| 
 | |
|       unique_ptr<Derived> func_returning_unique_ptr (.....);
 | |
|       ...
 | |
|       unique_ptr<Base> ptr = func_returning_unique_ptr (.....);
 | |
|   */
 | |
|   template<typename T1, typename D1>
 | |
|   unique_ptr_base (const unique_ptr_base<T1, D1> &other) throw ()
 | |
|     : m_ptr (const_cast<unique_ptr_base<T1, D1> &> (other).release ()) {}
 | |
| 
 | |
|   /* The "move" assignment operator.  Really an lvalue ref copy
 | |
|      assignment operator that actually moves.  See comments above.  */
 | |
|   unique_ptr_base &operator= (const unique_ptr_base &other) throw ()
 | |
|   {
 | |
|     reset (const_cast<unique_ptr_base &> (other).release ());
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   /* Converting "move" assignment.  Really an lvalue ref converting
 | |
|      copy assignment operator that moves.  See comments above.  */
 | |
|   template<typename T1, typename D1>
 | |
|   unique_ptr_base &operator= (const unique_ptr_base<T1, D1> &other) throw ()
 | |
|   {
 | |
|     reset (const_cast<unique_ptr_base<T1, D1> &> (other).release ());
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   /* std::unique_ptr does not allow assignment, except from nullptr.
 | |
|      nullptr doesn't exist in C++03, so we allow assignment from NULL
 | |
|      instead [ptr = NULL;].
 | |
|   */
 | |
|   unique_ptr_base &operator= (detail::nullptr_t *) throw ()
 | |
|   {
 | |
|     reset ();
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   ~unique_ptr_base () { call_deleter (); }
 | |
| 
 | |
|   /* "explicit operator bool ()" emulation using the safe bool
 | |
|      idiom.  */
 | |
| private:
 | |
|   typedef void (unique_ptr_base::*explicit_operator_bool) () const;
 | |
|   void this_type_does_not_support_comparisons () const {}
 | |
| 
 | |
| public:
 | |
|   operator explicit_operator_bool () const
 | |
|   {
 | |
|     return (m_ptr != NULL
 | |
| 	    ? &unique_ptr_base::this_type_does_not_support_comparisons
 | |
| 	    : 0);
 | |
|   }
 | |
| 
 | |
|   element_type *get () const throw () { return m_ptr; }
 | |
| 
 | |
|   element_type *release () throw ()
 | |
|   {
 | |
|     pointer tmp = m_ptr;
 | |
|     m_ptr = NULL;
 | |
|     return tmp;
 | |
|   }
 | |
| 
 | |
|   void reset (element_type *p = NULL) throw ()
 | |
|   {
 | |
|     if (p != m_ptr)
 | |
|       {
 | |
| 	call_deleter ();
 | |
| 	m_ptr = p;
 | |
|       }
 | |
|   }
 | |
| 
 | |
| private:
 | |
| 
 | |
|   /* Call the deleter.  Note we assume the deleter is "stateless".  */
 | |
|   void call_deleter ()
 | |
|   {
 | |
|     D d;
 | |
| 
 | |
|     d (m_ptr);
 | |
|   }
 | |
| 
 | |
|   element_type *m_ptr;
 | |
| };
 | |
| 
 | |
| } /* namespace detail */
 | |
| 
 | |
| /* Macro used to create a unique_ptr_base "partial specialization" --
 | |
|    a subclass that uses a specific deleter.  Basically this re-defines
 | |
|    the necessary constructors.  This is necessary because C++03
 | |
|    doesn't support inheriting constructors with "using".  While at it,
 | |
|    we inherit the assignment operator.  TYPE is the name of the type
 | |
|    being defined.  Assumes that 'base_type' is a typedef of the
 | |
|    baseclass TYPE is inheriting from.  */
 | |
| #define DEFINE_GNU_UNIQUE_PTR(TYPE)						\
 | |
| public:									\
 | |
|   explicit TYPE (T *p = NULL) throw ()					\
 | |
|     : base_type (p) {}							\
 | |
| 									\
 | |
|   TYPE (const TYPE &other) throw () : base_type (other) {}		\
 | |
| 									\
 | |
|   TYPE (detail::nullptr_t *) throw () : base_type (NULL) {}		\
 | |
| 									\
 | |
|   template<typename T1, typename D1>					\
 | |
|   TYPE (const detail::unique_ptr_base<T1, D1> &other) throw ()		\
 | |
|     : base_type (other) {}						\
 | |
| 									\
 | |
|   using base_type::operator=;
 | |
| 
 | |
| /* Define single-object gnu::unique_ptr.  */
 | |
| 
 | |
| template <typename T, typename D = default_delete<T> >
 | |
| class unique_ptr : public detail::unique_ptr_base<T, D>
 | |
| {
 | |
|   typedef detail::unique_ptr_base<T, D> base_type;
 | |
| 
 | |
|   DEFINE_GNU_UNIQUE_PTR (unique_ptr)
 | |
| 
 | |
| public:
 | |
|   /* Dereferencing.  */
 | |
|   T &operator* () const throw () { return *this->get (); }
 | |
|   T *operator-> () const throw () { return this->get (); }
 | |
| };
 | |
| 
 | |
| /* Define gnu::unique_ptr specialization for T[].  */
 | |
| 
 | |
| template <typename T, typename D>
 | |
| class unique_ptr<T[], D> : public detail::unique_ptr_base<T, D>
 | |
| {
 | |
|   typedef detail::unique_ptr_base<T, D> base_type;
 | |
| 
 | |
|   DEFINE_GNU_UNIQUE_PTR (unique_ptr)
 | |
| 
 | |
| public:
 | |
|   /* Indexing operator.  */
 | |
|   T &operator[] (size_t i) const { return this->get ()[i]; }
 | |
| };
 | |
| 
 | |
| /* Comparison operators.  */
 | |
| 
 | |
| template <typename T, typename D,
 | |
| 	  typename U, typename E>
 | |
| inline bool
 | |
| operator== (const detail::unique_ptr_base<T, D> &x,
 | |
| 	    const detail::unique_ptr_base<U, E> &y)
 | |
| { return x.get() == y.get(); }
 | |
| 
 | |
| template <typename T, typename D,
 | |
| 	  typename U, typename E>
 | |
| inline bool
 | |
| operator!= (const detail::unique_ptr_base<T, D> &x,
 | |
| 	    const detail::unique_ptr_base<U, E> &y)
 | |
| { return x.get() != y.get(); }
 | |
| 
 | |
| template<typename T, typename D,
 | |
| 	 typename U, typename E>
 | |
| inline bool
 | |
| operator< (const detail::unique_ptr_base<T, D> &x,
 | |
| 	   const detail::unique_ptr_base<U, E> &y)
 | |
| { return x.get() < y.get (); }
 | |
| 
 | |
| template<typename T, typename D,
 | |
| 	 typename U, typename E>
 | |
| inline bool
 | |
| operator<= (const detail::unique_ptr_base<T, D> &x,
 | |
| 	    const detail::unique_ptr_base<U, E> &y)
 | |
| { return !(y < x); }
 | |
| 
 | |
| template<typename T, typename D,
 | |
| 	 typename U, typename E>
 | |
| inline bool
 | |
| operator> (const detail::unique_ptr_base<T, D> &x,
 | |
| 	   const detail::unique_ptr_base<U, E> &y)
 | |
| { return y < x; }
 | |
| 
 | |
| template<typename T, typename D,
 | |
| 	 typename U, typename E>
 | |
| inline bool
 | |
| operator>= (const detail::unique_ptr_base<T, D> &x,
 | |
| 	    const detail::unique_ptr_base<U, E> &y)
 | |
| { return !(x < y); }
 | |
| 
 | |
| /* std::move "emulation".  This is as simple as it can be -- no
 | |
|    attempt is made to emulate rvalue references.  This relies on T
 | |
|    having move semantics like std::auto_ptr.
 | |
|    I.e., copy/assignment actually moves.  */
 | |
| 
 | |
| template<typename T>
 | |
| const T&
 | |
| move (T& v)
 | |
| {
 | |
|   return v;
 | |
| }
 | |
| 
 | |
| #endif /* C++11 */
 | |
| 
 | |
| /* Define gnu::unique_xmalloc_ptr, a gnu::unique_ptr that manages
 | |
|    xmalloc'ed memory.  */
 | |
| 
 | |
| /* The deleter for gnu::unique_xmalloc_ptr.  Uses free.  */
 | |
| template <typename T>
 | |
| struct xmalloc_deleter
 | |
| {
 | |
|   void operator() (T *ptr) const { free (ptr); }
 | |
| };
 | |
| 
 | |
| /* Same, for arrays.  */
 | |
| template <typename T>
 | |
| struct xmalloc_deleter<T[]>
 | |
| {
 | |
|   void operator() (T *ptr) const { free (ptr); }
 | |
| };
 | |
| 
 | |
| #if __cplusplus >= 201103
 | |
| 
 | |
| /* In C++11, we just import the standard unique_ptr to our namespace
 | |
|    with a custom deleter.  */
 | |
| 
 | |
| template<typename T> using unique_xmalloc_ptr
 | |
|   = std::unique_ptr<T, xmalloc_deleter<T>>;
 | |
| 
 | |
| #else /* C++11 */
 | |
| 
 | |
| /* In C++03, we don't have template aliases, so we need to define a
 | |
|    subclass instead, and re-define the constructors, because C++03
 | |
|    doesn't support inheriting constructors either.  */
 | |
| 
 | |
| template <typename T>
 | |
| class unique_xmalloc_ptr : public unique_ptr<T, xmalloc_deleter<T> >
 | |
| {
 | |
|   typedef unique_ptr<T, xmalloc_deleter<T> > base_type;
 | |
| 
 | |
|   DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
 | |
| };
 | |
| 
 | |
| /* Define gnu::unique_xmalloc_ptr specialization for T[].  */
 | |
| 
 | |
| template <typename T>
 | |
| class unique_xmalloc_ptr<T[]> : public unique_ptr<T[], xmalloc_deleter<T[]> >
 | |
| {
 | |
|   typedef unique_ptr<T[], xmalloc_deleter<T[]> > base_type;
 | |
| 
 | |
|   DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
 | |
| };
 | |
| 
 | |
| #endif /* C++11 */
 | |
| 
 | |
| } /* namespace gnu */
 | |
| 
 | |
| #endif /* GNU_UNIQUE_PTR_H */
 |