localpointer.h (19985B)
1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * 6 * Copyright (C) 2009-2016, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 * 9 ******************************************************************************* 10 * file name: localpointer.h 11 * encoding: UTF-8 12 * tab size: 8 (not used) 13 * indentation:4 14 * 15 * created on: 2009nov13 16 * created by: Markus W. Scherer 17 */ 18 19 #ifndef __LOCALPOINTER_H__ 20 #define __LOCALPOINTER_H__ 21 22 /** 23 * \file 24 * \brief C++ API: "Smart pointers" for use with and in ICU4C C++ code. 25 * 26 * These classes are inspired by 27 * - std::auto_ptr 28 * - boost::scoped_ptr & boost::scoped_array 29 * - Taligent Safe Pointers (TOnlyPointerTo) 30 * 31 * but none of those provide for all of the goals for ICU smart pointers: 32 * - Smart pointer owns the object and releases it when it goes out of scope. 33 * - No transfer of ownership via copy/assignment to reduce misuse. Simpler & more robust. 34 * - ICU-compatible: No exceptions. 35 * - Need to be able to orphan/release the pointer and its ownership. 36 * - Need variants for normal C++ object pointers, C++ arrays, and ICU C service objects. 37 * 38 * For details see https://icu.unicode.org/design/cpp/scoped_ptr 39 */ 40 41 #include "unicode/utypes.h" 42 43 #if U_SHOW_CPLUSPLUS_API 44 45 #include <memory> 46 47 U_NAMESPACE_BEGIN 48 49 /** 50 * "Smart pointer" base class; do not use directly: use LocalPointer etc. 51 * 52 * Base class for smart pointer classes that do not throw exceptions. 53 * 54 * Do not use this base class directly, since it does not delete its pointer. 55 * A subclass must implement methods that delete the pointer: 56 * Destructor and adoptInstead(). 57 * 58 * There is no operator T *() provided because the programmer must decide 59 * whether to use getAlias() (without transfer of ownership) or orphan() 60 * (with transfer of ownership and NULLing of the pointer). 61 * 62 * @see LocalPointer 63 * @see LocalArray 64 * @see U_DEFINE_LOCAL_OPEN_POINTER 65 * @stable ICU 4.4 66 */ 67 template<typename T> 68 class LocalPointerBase { 69 public: 70 // No heap allocation. Use only on the stack. 71 static void* U_EXPORT2 operator new(size_t) = delete; 72 static void* U_EXPORT2 operator new[](size_t) = delete; 73 static void* U_EXPORT2 operator new(size_t, void*) = delete; 74 75 /** 76 * Constructor takes ownership. 77 * @param p simple pointer to an object that is adopted 78 * @stable ICU 4.4 79 */ 80 explicit LocalPointerBase(T *p=nullptr) : ptr(p) {} 81 /** 82 * Destructor deletes the object it owns. 83 * Subclass must override: Base class does nothing. 84 * @stable ICU 4.4 85 */ 86 ~LocalPointerBase() { /* delete ptr; */ } 87 /** 88 * nullptr check. 89 * @return true if ==nullptr 90 * @stable ICU 4.4 91 */ 92 UBool isNull() const { return ptr==nullptr; } 93 /** 94 * nullptr check. 95 * @return true if !=nullptr 96 * @stable ICU 4.4 97 */ 98 UBool isValid() const { return ptr!=nullptr; } 99 /** 100 * Comparison with a simple pointer, so that existing code 101 * with ==nullptr need not be changed. 102 * @param other simple pointer for comparison 103 * @return true if this pointer value equals other 104 * @stable ICU 4.4 105 */ 106 bool operator==(const T *other) const { return ptr==other; } 107 /** 108 * Comparison with a simple pointer, so that existing code 109 * with !=nullptr need not be changed. 110 * @param other simple pointer for comparison 111 * @return true if this pointer value differs from other 112 * @stable ICU 4.4 113 */ 114 bool operator!=(const T *other) const { return ptr!=other; } 115 /** 116 * Access without ownership change. 117 * @return the pointer value 118 * @stable ICU 4.4 119 */ 120 T *getAlias() const { return ptr; } 121 /** 122 * Access without ownership change. 123 * @return the pointer value as a reference 124 * @stable ICU 4.4 125 */ 126 T &operator*() const { return *ptr; } 127 /** 128 * Access without ownership change. 129 * @return the pointer value 130 * @stable ICU 4.4 131 */ 132 T *operator->() const { return ptr; } 133 /** 134 * Gives up ownership; the internal pointer becomes nullptr. 135 * @return the pointer value; 136 * caller becomes responsible for deleting the object 137 * @stable ICU 4.4 138 */ 139 T *orphan() { 140 T *p=ptr; 141 ptr=nullptr; 142 return p; 143 } 144 /** 145 * Deletes the object it owns, 146 * and adopts (takes ownership of) the one passed in. 147 * Subclass must override: Base class does not delete the object. 148 * @param p simple pointer to an object that is adopted 149 * @stable ICU 4.4 150 */ 151 void adoptInstead(T *p) { 152 // delete ptr; 153 ptr=p; 154 } 155 protected: 156 /** 157 * Actual pointer. 158 * @internal 159 */ 160 T *ptr; 161 private: 162 // No comparison operators with other LocalPointerBases. 163 bool operator==(const LocalPointerBase<T> &other) = delete; 164 bool operator!=(const LocalPointerBase<T> &other) = delete; 165 // No ownership sharing: No copy constructor, no assignment operator. 166 LocalPointerBase(const LocalPointerBase<T> &other) = delete; 167 void operator=(const LocalPointerBase<T> &other) = delete; 168 }; 169 170 /** 171 * "Smart pointer" class, deletes objects via the standard C++ delete operator. 172 * For most methods see the LocalPointerBase base class. 173 * 174 * Usage example: 175 * \code 176 * LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005)); 177 * int32_t length=s->length(); // 2 178 * char16_t lead=s->charAt(0); // 0xd900 179 * if(some condition) { return; } // no need to explicitly delete the pointer 180 * s.adoptInstead(new UnicodeString((char16_t)0xfffc)); 181 * length=s->length(); // 1 182 * // no need to explicitly delete the pointer 183 * \endcode 184 * 185 * @see LocalPointerBase 186 * @stable ICU 4.4 187 */ 188 template<typename T> 189 class LocalPointer : public LocalPointerBase<T> { 190 public: 191 using LocalPointerBase<T>::operator*; 192 using LocalPointerBase<T>::operator->; 193 /** 194 * Constructor takes ownership. 195 * @param p simple pointer to an object that is adopted 196 * @stable ICU 4.4 197 */ 198 explicit LocalPointer(T *p=nullptr) : LocalPointerBase<T>(p) {} 199 /** 200 * Constructor takes ownership and reports an error if nullptr. 201 * 202 * This constructor is intended to be used with other-class constructors 203 * that may report a failure UErrorCode, 204 * so that callers need to check only for U_FAILURE(errorCode) 205 * and not also separately for isNull(). 206 * 207 * @param p simple pointer to an object that is adopted 208 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 209 * if p==nullptr and no other failure code had been set 210 * @stable ICU 55 211 */ 212 LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) { 213 if(p==nullptr && U_SUCCESS(errorCode)) { 214 errorCode=U_MEMORY_ALLOCATION_ERROR; 215 } 216 } 217 /** 218 * Move constructor, leaves src with isNull(). 219 * @param src source smart pointer 220 * @stable ICU 56 221 */ 222 LocalPointer(LocalPointer<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) { 223 src.ptr=nullptr; 224 } 225 226 /** 227 * Constructs a LocalPointer from a C++11 std::unique_ptr. 228 * The LocalPointer steals the object owned by the std::unique_ptr. 229 * 230 * This constructor works via move semantics. If your std::unique_ptr is 231 * in a local variable, you must use std::move. 232 * 233 * @param p The std::unique_ptr from which the pointer will be stolen. 234 * @stable ICU 64 235 */ 236 explicit LocalPointer(std::unique_ptr<T> &&p) 237 : LocalPointerBase<T>(p.release()) {} 238 239 /** 240 * Destructor deletes the object it owns. 241 * @stable ICU 4.4 242 */ 243 ~LocalPointer() { 244 delete LocalPointerBase<T>::ptr; 245 } 246 /** 247 * Move assignment operator, leaves src with isNull(). 248 * The behavior is undefined if *this and src are the same object. 249 * @param src source smart pointer 250 * @return *this 251 * @stable ICU 56 252 */ 253 LocalPointer<T> &operator=(LocalPointer<T> &&src) noexcept { 254 delete LocalPointerBase<T>::ptr; 255 LocalPointerBase<T>::ptr=src.ptr; 256 src.ptr=nullptr; 257 return *this; 258 } 259 260 /** 261 * Move-assign from an std::unique_ptr to this LocalPointer. 262 * Steals the pointer from the std::unique_ptr. 263 * 264 * @param p The std::unique_ptr from which the pointer will be stolen. 265 * @return *this 266 * @stable ICU 64 267 */ 268 LocalPointer<T> &operator=(std::unique_ptr<T> &&p) noexcept { 269 adoptInstead(p.release()); 270 return *this; 271 } 272 273 /** 274 * Swap pointers. 275 * @param other other smart pointer 276 * @stable ICU 56 277 */ 278 void swap(LocalPointer<T> &other) noexcept { 279 T *temp=LocalPointerBase<T>::ptr; 280 LocalPointerBase<T>::ptr=other.ptr; 281 other.ptr=temp; 282 } 283 /** 284 * Non-member LocalPointer swap function. 285 * @param p1 will get p2's pointer 286 * @param p2 will get p1's pointer 287 * @stable ICU 56 288 */ 289 friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) noexcept { 290 p1.swap(p2); 291 } 292 /** 293 * Deletes the object it owns, 294 * and adopts (takes ownership of) the one passed in. 295 * @param p simple pointer to an object that is adopted 296 * @stable ICU 4.4 297 */ 298 void adoptInstead(T *p) { 299 delete LocalPointerBase<T>::ptr; 300 LocalPointerBase<T>::ptr=p; 301 } 302 /** 303 * Deletes the object it owns, 304 * and adopts (takes ownership of) the one passed in. 305 * 306 * If U_FAILURE(errorCode), then the current object is retained and the new one deleted. 307 * 308 * If U_SUCCESS(errorCode) but the input pointer is nullptr, 309 * then U_MEMORY_ALLOCATION_ERROR is set, 310 * the current object is deleted, and nullptr is set. 311 * 312 * @param p simple pointer to an object that is adopted 313 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 314 * if p==nullptr and no other failure code had been set 315 * @stable ICU 55 316 */ 317 void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) { 318 if(U_SUCCESS(errorCode)) { 319 delete LocalPointerBase<T>::ptr; 320 LocalPointerBase<T>::ptr=p; 321 if(p==nullptr) { 322 errorCode=U_MEMORY_ALLOCATION_ERROR; 323 } 324 } else { 325 delete p; 326 } 327 } 328 329 /** 330 * Conversion operator to a C++11 std::unique_ptr. 331 * Disowns the object and gives it to the returned std::unique_ptr. 332 * 333 * This operator works via move semantics. If your LocalPointer is 334 * in a local variable, you must use std::move. 335 * 336 * @return An std::unique_ptr owning the pointer previously owned by this 337 * icu::LocalPointer. 338 * @stable ICU 64 339 */ 340 operator std::unique_ptr<T> () && { 341 return std::unique_ptr<T>(LocalPointerBase<T>::orphan()); 342 } 343 }; 344 345 /** 346 * "Smart pointer" class, deletes objects via the C++ array delete[] operator. 347 * For most methods see the LocalPointerBase base class. 348 * Adds operator[] for array item access. 349 * 350 * Usage example: 351 * \code 352 * LocalArray<UnicodeString> a(new UnicodeString[2]); 353 * a[0].append((char16_t)0x61); 354 * if(some condition) { return; } // no need to explicitly delete the array 355 * a.adoptInstead(new UnicodeString[4]); 356 * a[3].append((char16_t)0x62).append((char16_t)0x63).reverse(); 357 * // no need to explicitly delete the array 358 * \endcode 359 * 360 * @see LocalPointerBase 361 * @stable ICU 4.4 362 */ 363 template<typename T> 364 class LocalArray : public LocalPointerBase<T> { 365 public: 366 using LocalPointerBase<T>::operator*; 367 using LocalPointerBase<T>::operator->; 368 /** 369 * Constructor takes ownership. 370 * @param p simple pointer to an array of T objects that is adopted 371 * @stable ICU 4.4 372 */ 373 explicit LocalArray(T *p=nullptr) : LocalPointerBase<T>(p) {} 374 /** 375 * Constructor takes ownership and reports an error if nullptr. 376 * 377 * This constructor is intended to be used with other-class constructors 378 * that may report a failure UErrorCode, 379 * so that callers need to check only for U_FAILURE(errorCode) 380 * and not also separately for isNull(). 381 * 382 * @param p simple pointer to an array of T objects that is adopted 383 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 384 * if p==nullptr and no other failure code had been set 385 * @stable ICU 56 386 */ 387 LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) { 388 if(p==nullptr && U_SUCCESS(errorCode)) { 389 errorCode=U_MEMORY_ALLOCATION_ERROR; 390 } 391 } 392 /** 393 * Move constructor, leaves src with isNull(). 394 * @param src source smart pointer 395 * @stable ICU 56 396 */ 397 LocalArray(LocalArray<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) { 398 src.ptr=nullptr; 399 } 400 401 /** 402 * Constructs a LocalArray from a C++11 std::unique_ptr of an array type. 403 * The LocalPointer steals the array owned by the std::unique_ptr. 404 * 405 * This constructor works via move semantics. If your std::unique_ptr is 406 * in a local variable, you must use std::move. 407 * 408 * @param p The std::unique_ptr from which the array will be stolen. 409 * @stable ICU 64 410 */ 411 explicit LocalArray(std::unique_ptr<T[]> &&p) 412 : LocalPointerBase<T>(p.release()) {} 413 414 /** 415 * Destructor deletes the array it owns. 416 * @stable ICU 4.4 417 */ 418 ~LocalArray() { 419 delete[] LocalPointerBase<T>::ptr; 420 } 421 /** 422 * Move assignment operator, leaves src with isNull(). 423 * The behavior is undefined if *this and src are the same object. 424 * @param src source smart pointer 425 * @return *this 426 * @stable ICU 56 427 */ 428 LocalArray<T> &operator=(LocalArray<T> &&src) noexcept { 429 delete[] LocalPointerBase<T>::ptr; 430 LocalPointerBase<T>::ptr=src.ptr; 431 src.ptr=nullptr; 432 return *this; 433 } 434 435 /** 436 * Move-assign from an std::unique_ptr to this LocalPointer. 437 * Steals the array from the std::unique_ptr. 438 * 439 * @param p The std::unique_ptr from which the array will be stolen. 440 * @return *this 441 * @stable ICU 64 442 */ 443 LocalArray<T> &operator=(std::unique_ptr<T[]> &&p) noexcept { 444 adoptInstead(p.release()); 445 return *this; 446 } 447 448 /** 449 * Swap pointers. 450 * @param other other smart pointer 451 * @stable ICU 56 452 */ 453 void swap(LocalArray<T> &other) noexcept { 454 T *temp=LocalPointerBase<T>::ptr; 455 LocalPointerBase<T>::ptr=other.ptr; 456 other.ptr=temp; 457 } 458 /** 459 * Non-member LocalArray swap function. 460 * @param p1 will get p2's pointer 461 * @param p2 will get p1's pointer 462 * @stable ICU 56 463 */ 464 friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) noexcept { 465 p1.swap(p2); 466 } 467 /** 468 * Deletes the array it owns, 469 * and adopts (takes ownership of) the one passed in. 470 * @param p simple pointer to an array of T objects that is adopted 471 * @stable ICU 4.4 472 */ 473 void adoptInstead(T *p) { 474 delete[] LocalPointerBase<T>::ptr; 475 LocalPointerBase<T>::ptr=p; 476 } 477 /** 478 * Deletes the array it owns, 479 * and adopts (takes ownership of) the one passed in. 480 * 481 * If U_FAILURE(errorCode), then the current array is retained and the new one deleted. 482 * 483 * If U_SUCCESS(errorCode) but the input pointer is nullptr, 484 * then U_MEMORY_ALLOCATION_ERROR is set, 485 * the current array is deleted, and nullptr is set. 486 * 487 * @param p simple pointer to an array of T objects that is adopted 488 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 489 * if p==nullptr and no other failure code had been set 490 * @stable ICU 56 491 */ 492 void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) { 493 if(U_SUCCESS(errorCode)) { 494 delete[] LocalPointerBase<T>::ptr; 495 LocalPointerBase<T>::ptr=p; 496 if(p==nullptr) { 497 errorCode=U_MEMORY_ALLOCATION_ERROR; 498 } 499 } else { 500 delete[] p; 501 } 502 } 503 /** 504 * Array item access (writable). 505 * No index bounds check. 506 * @param i array index 507 * @return reference to the array item 508 * @stable ICU 4.4 509 */ 510 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; } 511 512 /** 513 * Conversion operator to a C++11 std::unique_ptr. 514 * Disowns the object and gives it to the returned std::unique_ptr. 515 * 516 * This operator works via move semantics. If your LocalPointer is 517 * in a local variable, you must use std::move. 518 * 519 * @return An std::unique_ptr owning the pointer previously owned by this 520 * icu::LocalPointer. 521 * @stable ICU 64 522 */ 523 operator std::unique_ptr<T[]> () && { 524 return std::unique_ptr<T[]>(LocalPointerBase<T>::orphan()); 525 } 526 }; 527 528 /** 529 * \def U_DEFINE_LOCAL_OPEN_POINTER 530 * "Smart pointer" definition macro, deletes objects via the closeFunction. 531 * Defines a subclass of LocalPointerBase which works just 532 * like LocalPointer<Type> except that this subclass will use the closeFunction 533 * rather than the C++ delete operator. 534 * 535 * Usage example: 536 * \code 537 * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode)); 538 * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(), 539 * utf8Out, (int32_t)sizeof(utf8Out), 540 * utf8In, utf8InLength, &errorCode); 541 * if(U_FAILURE(errorCode)) { return; } // no need to explicitly delete the UCaseMap 542 * \endcode 543 * 544 * @see LocalPointerBase 545 * @see LocalPointer 546 * @stable ICU 4.4 547 */ 548 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \ 549 using LocalPointerClassName = internal::LocalOpenPointer<Type, closeFunction> 550 551 #ifndef U_IN_DOXYGEN 552 namespace internal { 553 /** 554 * Implementation, do not use directly: use U_DEFINE_LOCAL_OPEN_POINTER. 555 * 556 * @see U_DEFINE_LOCAL_OPEN_POINTER 557 * @internal 558 */ 559 template <typename Type, auto closeFunction> 560 class LocalOpenPointer : public LocalPointerBase<Type> { 561 using LocalPointerBase<Type>::ptr; 562 public: 563 using LocalPointerBase<Type>::operator*; 564 using LocalPointerBase<Type>::operator->; 565 explicit LocalOpenPointer(Type *p=nullptr) : LocalPointerBase<Type>(p) {} 566 LocalOpenPointer(LocalOpenPointer &&src) noexcept 567 : LocalPointerBase<Type>(src.ptr) { 568 src.ptr=nullptr; 569 } 570 /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ 571 explicit LocalOpenPointer(std::unique_ptr<Type, decltype(closeFunction)> &&p) 572 : LocalPointerBase<Type>(p.release()) {} 573 ~LocalOpenPointer() { if (ptr != nullptr) { closeFunction(ptr); } } 574 LocalOpenPointer &operator=(LocalOpenPointer &&src) noexcept { 575 if (ptr != nullptr) { closeFunction(ptr); } 576 LocalPointerBase<Type>::ptr=src.ptr; 577 src.ptr=nullptr; 578 return *this; 579 } 580 /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ 581 LocalOpenPointer &operator=(std::unique_ptr<Type, decltype(closeFunction)> &&p) { 582 adoptInstead(p.release()); 583 return *this; 584 } 585 void swap(LocalOpenPointer &other) noexcept { 586 Type *temp=LocalPointerBase<Type>::ptr; 587 LocalPointerBase<Type>::ptr=other.ptr; 588 other.ptr=temp; 589 } 590 friend inline void swap(LocalOpenPointer &p1, LocalOpenPointer &p2) noexcept { 591 p1.swap(p2); 592 } 593 void adoptInstead(Type *p) { 594 if (ptr != nullptr) { closeFunction(ptr); } 595 ptr=p; 596 } 597 operator std::unique_ptr<Type, decltype(closeFunction)> () && { 598 return std::unique_ptr<Type, decltype(closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction); 599 } 600 }; 601 } // namespace internal 602 #endif 603 604 U_NAMESPACE_END 605 606 #endif /* U_SHOW_CPLUSPLUS_API */ 607 #endif /* __LOCALPOINTER_H__ */