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