| /* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03. | |
| Copyright (C) 2007-2021 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 */ |