1 /* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03. 2 3 Copyright (C) 2007-2018 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 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. 11 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. 16 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/>. */ 19 20 /* gnu::unique_ptr defines a C++ owning smart pointer that exposes a 21 subset of the std::unique_ptr API. 22 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. 27 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. 32 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. 37 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. 43 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. 53 54 Usage notes: 55 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). 59 60 - Since there's no nullptr in C++03, gnu::unique_ptr allows 61 implicit initialization and assignment from NULL instead. 62 63 - To check whether there's an associated managed object, all these 64 work as expected: 65 66 if (ptr) 67 if (!ptr) 68 if (ptr != NULL) 69 if (ptr == NULL) 70 if (NULL != ptr) 71 if (NULL == ptr) 72 */ 73 74 #ifndef GNU_UNIQUE_PTR_H 75 #define GNU_UNIQUE_PTR_H 1 76 77 #if __cplusplus >= 201103 78 # include <memory> 79 #endif 80 81 namespace gnu 82 { 83 84 #if __cplusplus >= 201103 85 86 /* In C++11 mode, all we need is import the standard 87 std::unique_ptr. */ 88 template<typename T> using unique_ptr = std::unique_ptr<T>; 89 90 /* Pull in move as well. */ 91 using std::move; 92 93 #else /* C++11 */ 94 95 /* Default destruction policy used by gnu::unique_ptr when no deleter 96 is specified. Uses delete. */ 97 98 template<typename T> 99 struct default_delete 100 { 101 void operator () (T *ptr) const { delete ptr; } 102 }; 103 104 /* Specialization for arrays. Uses delete[]. */ 105 106 template<typename T> 107 struct default_delete<T[]> 108 { 109 void operator () (T *ptr) const { delete [] ptr; } 110 }; 111 112 namespace detail 113 { 114 /* Type used to support implicit construction from NULL: 115 116 gnu::unique_ptr<foo> func (....) 117 { 118 return NULL; 119 } 120 121 and assignment from NULL: 122 123 gnu::unique_ptr<foo> ptr (....); 124 ... 125 ptr = NULL; 126 127 It is intentionally not defined anywhere. */ 128 struct nullptr_t; 129 130 /* Base class of our unique_ptr emulation. Contains code common to 131 both unique_ptr<T, D> and unique_ptr<T[], D>. */ 132 133 template<typename T, typename D> 134 class unique_ptr_base 135 { 136 public: 137 typedef T *pointer; 138 typedef T element_type; 139 typedef D deleter_type; 140 141 /* Takes ownership of a pointer. P is a pointer to an object of 142 element_type type. Defaults to NULL. */ 143 explicit unique_ptr_base (element_type *p = NULL) throw () : m_ptr (p) {} 144 145 /* The "move" constructor. Really a copy constructor that actually 146 moves. Even though std::unique_ptr is not copyable, our little 147 simpler emulation allows it, because: 148 149 - There are no rvalue references in C++03. Our move emulation 150 instead relies on copy/assignment moving, like std::auto_ptr. 151 - RVO/NRVO requires an accessible copy constructor 152 */ 153 unique_ptr_base (const unique_ptr_base &other) throw () 154 : m_ptr (const_cast<unique_ptr_base &> (other).release ()) {} 155 156 /* Converting "move" constructor. Really an lvalue ref converting 157 constructor that actually moves. This allows constructs such as: 158 159 unique_ptr<Derived> func_returning_unique_ptr (.....); 160 ... 161 unique_ptr<Base> ptr = func_returning_unique_ptr (.....); 162 */ 163 template<typename T1, typename D1> 164 unique_ptr_base (const unique_ptr_base<T1, D1> &other) throw () 165 : m_ptr (const_cast<unique_ptr_base<T1, D1> &> (other).release ()) {} 166 167 /* The "move" assignment operator. Really an lvalue ref copy 168 assignment operator that actually moves. See comments above. */ 169 unique_ptr_base &operator= (const unique_ptr_base &other) throw () 170 { 171 reset (const_cast<unique_ptr_base &> (other).release ()); 172 return *this; 173 } 174 175 /* Converting "move" assignment. Really an lvalue ref converting 176 copy assignment operator that moves. See comments above. */ 177 template<typename T1, typename D1> 178 unique_ptr_base &operator= (const unique_ptr_base<T1, D1> &other) throw () 179 { 180 reset (const_cast<unique_ptr_base<T1, D1> &> (other).release ()); 181 return *this; 182 } 183 184 /* std::unique_ptr does not allow assignment, except from nullptr. 185 nullptr doesn't exist in C++03, so we allow assignment from NULL 186 instead [ptr = NULL;]. 187 */ 188 unique_ptr_base &operator= (detail::nullptr_t *) throw () 189 { 190 reset (); 191 return *this; 192 } 193 194 ~unique_ptr_base () { call_deleter (); } 195 196 /* "explicit operator bool ()" emulation using the safe bool 197 idiom. */ 198 private: 199 typedef void (unique_ptr_base::*explicit_operator_bool) () const; 200 void this_type_does_not_support_comparisons () const {} 201 202 public: 203 operator explicit_operator_bool () const 204 { 205 return (m_ptr != NULL 206 ? &unique_ptr_base::this_type_does_not_support_comparisons 207 : 0); 208 } 209 210 element_type *get () const throw () { return m_ptr; } 211 212 element_type *release () throw () 213 { 214 pointer tmp = m_ptr; 215 m_ptr = NULL; 216 return tmp; 217 } 218 219 void reset (element_type *p = NULL) throw () 220 { 221 if (p != m_ptr) 222 { 223 call_deleter (); 224 m_ptr = p; 225 } 226 } 227 228 private: 229 230 /* Call the deleter. Note we assume the deleter is "stateless". */ 231 void call_deleter () 232 { 233 D d; 234 235 d (m_ptr); 236 } 237 238 element_type *m_ptr; 239 }; 240 241 } /* namespace detail */ 242 243 /* Macro used to create a unique_ptr_base "partial specialization" -- 244 a subclass that uses a specific deleter. Basically this re-defines 245 the necessary constructors. This is necessary because C++03 246 doesn't support inheriting constructors with "using". While at it, 247 we inherit the assignment operator. TYPE is the name of the type 248 being defined. Assumes that 'base_type' is a typedef of the 249 baseclass TYPE is inheriting from. */ 250 #define DEFINE_GNU_UNIQUE_PTR(TYPE) \ 251 public: \ 252 explicit TYPE (T *p = NULL) throw () \ 253 : base_type (p) {} \ 254 \ 255 TYPE (const TYPE &other) throw () : base_type (other) {} \ 256 \ 257 TYPE (detail::nullptr_t *) throw () : base_type (NULL) {} \ 258 \ 259 template<typename T1, typename D1> \ 260 TYPE (const detail::unique_ptr_base<T1, D1> &other) throw () \ 261 : base_type (other) {} \ 262 \ 263 using base_type::operator=; 264 265 /* Define single-object gnu::unique_ptr. */ 266 267 template <typename T, typename D = default_delete<T> > 268 class unique_ptr : public detail::unique_ptr_base<T, D> 269 { 270 typedef detail::unique_ptr_base<T, D> base_type; 271 272 DEFINE_GNU_UNIQUE_PTR (unique_ptr) 273 274 public: 275 /* Dereferencing. */ 276 T &operator* () const throw () { return *this->get (); } 277 T *operator-> () const throw () { return this->get (); } 278 }; 279 280 /* Define gnu::unique_ptr specialization for T[]. */ 281 282 template <typename T, typename D> 283 class unique_ptr<T[], D> : public detail::unique_ptr_base<T, D> 284 { 285 typedef detail::unique_ptr_base<T, D> base_type; 286 287 DEFINE_GNU_UNIQUE_PTR (unique_ptr) 288 289 public: 290 /* Indexing operator. */ 291 T &operator[] (size_t i) const { return this->get ()[i]; } 292 }; 293 294 /* Comparison operators. */ 295 296 template <typename T, typename D, 297 typename U, typename E> 298 inline bool 299 operator== (const detail::unique_ptr_base<T, D> &x, 300 const detail::unique_ptr_base<U, E> &y) 301 { return x.get() == y.get(); } 302 303 template <typename T, typename D, 304 typename U, typename E> 305 inline bool 306 operator!= (const detail::unique_ptr_base<T, D> &x, 307 const detail::unique_ptr_base<U, E> &y) 308 { return x.get() != y.get(); } 309 310 template<typename T, typename D, 311 typename U, typename E> 312 inline bool 313 operator< (const detail::unique_ptr_base<T, D> &x, 314 const detail::unique_ptr_base<U, E> &y) 315 { return x.get() < y.get (); } 316 317 template<typename T, typename D, 318 typename U, typename E> 319 inline bool 320 operator<= (const detail::unique_ptr_base<T, D> &x, 321 const detail::unique_ptr_base<U, E> &y) 322 { return !(y < x); } 323 324 template<typename T, typename D, 325 typename U, typename E> 326 inline bool 327 operator> (const detail::unique_ptr_base<T, D> &x, 328 const detail::unique_ptr_base<U, E> &y) 329 { return y < x; } 330 331 template<typename T, typename D, 332 typename U, typename E> 333 inline bool 334 operator>= (const detail::unique_ptr_base<T, D> &x, 335 const detail::unique_ptr_base<U, E> &y) 336 { return !(x < y); } 337 338 /* std::move "emulation". This is as simple as it can be -- no 339 attempt is made to emulate rvalue references. Instead relies on 340 the fact that gnu::unique_ptr has move semantics like 341 std::auto_ptr. I.e., copy/assignment actually moves. */ 342 343 template<typename T, typename D> 344 unique_ptr<T, D> 345 move (unique_ptr<T, D> v) 346 { 347 return v; 348 } 349 350 #endif /* C++11 */ 351 352 /* Define gnu::unique_xmalloc_ptr, a gnu::unique_ptr that manages 353 xmalloc'ed memory. */ 354 355 /* The deleter for gnu::unique_xmalloc_ptr. Uses free. */ 356 template <typename T> 357 struct xmalloc_deleter 358 { operatorxmalloc_deleter359 void operator() (T *ptr) const { free (ptr); } 360 }; 361 362 /* Same, for arrays. */ 363 template <typename T> 364 struct xmalloc_deleter<T[]> 365 { 366 void operator() (T *ptr) const { free (ptr); } 367 }; 368 369 #if __cplusplus >= 201103 370 371 /* In C++11, we just import the standard unique_ptr to our namespace 372 with a custom deleter. */ 373 374 template<typename T> using unique_xmalloc_ptr 375 = std::unique_ptr<T, xmalloc_deleter<T>>; 376 377 #else /* C++11 */ 378 379 /* In C++03, we don't have template aliases, so we need to define a 380 subclass instead, and re-define the constructors, because C++03 381 doesn't support inheriting constructors either. */ 382 383 template <typename T> 384 class unique_xmalloc_ptr : public unique_ptr<T, xmalloc_deleter<T> > 385 { 386 typedef unique_ptr<T, xmalloc_deleter<T> > base_type; 387 388 DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr) 389 }; 390 391 /* Define gnu::unique_xmalloc_ptr specialization for T[]. */ 392 393 template <typename T> 394 class unique_xmalloc_ptr<T[]> : public unique_ptr<T[], xmalloc_deleter<T[]> > 395 { 396 typedef unique_ptr<T[], xmalloc_deleter<T[]> > base_type; 397 398 DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr) 399 }; 400 401 #endif /* C++11 */ 402 403 } /* namespace gnu */ 404 405 #endif /* GNU_UNIQUE_PTR_H */ 406