ICU 73.2  73.2
localpointer.h
Go to the documentation of this file.
00001 // © 2016 and later: Unicode, Inc. and others.
00002 // License & terms of use: http://www.unicode.org/copyright.html
00003 /*
00004 *******************************************************************************
00005 *
00006 *   Copyright (C) 2009-2016, International Business Machines
00007 *   Corporation and others.  All Rights Reserved.
00008 *
00009 *******************************************************************************
00010 *   file name:  localpointer.h
00011 *   encoding:   UTF-8
00012 *   tab size:   8 (not used)
00013 *   indentation:4
00014 *
00015 *   created on: 2009nov13
00016 *   created by: Markus W. Scherer
00017 */
00018 
00019 #ifndef __LOCALPOINTER_H__
00020 #define __LOCALPOINTER_H__
00021 
00041 #include "unicode/utypes.h"
00042 
00043 #if U_SHOW_CPLUSPLUS_API
00044 
00045 #include <memory>
00046 
00047 U_NAMESPACE_BEGIN
00048 
00067 template<typename T>
00068 class LocalPointerBase {
00069 public:
00070     // No heap allocation. Use only on the stack.
00071     static void* U_EXPORT2 operator new(size_t) = delete;
00072     static void* U_EXPORT2 operator new[](size_t) = delete;
00073 #if U_HAVE_PLACEMENT_NEW
00074     static void* U_EXPORT2 operator new(size_t, void*) = delete;
00075 #endif
00076 
00082     explicit LocalPointerBase(T *p=nullptr) : ptr(p) {}
00088     ~LocalPointerBase() { /* delete ptr; */ }
00094     UBool isNull() const { return ptr==nullptr; }
00100     UBool isValid() const { return ptr!=nullptr; }
00108     bool operator==(const T *other) const { return ptr==other; }
00116     bool operator!=(const T *other) const { return ptr!=other; }
00122     T *getAlias() const { return ptr; }
00128     T &operator*() const { return *ptr; }
00134     T *operator->() const { return ptr; }
00141     T *orphan() {
00142         T *p=ptr;
00143         ptr=nullptr;
00144         return p;
00145     }
00153     void adoptInstead(T *p) {
00154         // delete ptr;
00155         ptr=p;
00156     }
00157 protected:
00162     T *ptr;
00163 private:
00164     // No comparison operators with other LocalPointerBases.
00165     bool operator==(const LocalPointerBase<T> &other);
00166     bool operator!=(const LocalPointerBase<T> &other);
00167     // No ownership sharing: No copy constructor, no assignment operator.
00168     LocalPointerBase(const LocalPointerBase<T> &other);
00169     void operator=(const LocalPointerBase<T> &other);
00170 };
00171 
00190 template<typename T>
00191 class LocalPointer : public LocalPointerBase<T> {
00192 public:
00193     using LocalPointerBase<T>::operator*;
00194     using LocalPointerBase<T>::operator->;
00200     explicit LocalPointer(T *p=nullptr) : LocalPointerBase<T>(p) {}
00214     LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
00215         if(p==nullptr && U_SUCCESS(errorCode)) {
00216             errorCode=U_MEMORY_ALLOCATION_ERROR;
00217         }
00218     }
00224     LocalPointer(LocalPointer<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
00225         src.ptr=nullptr;
00226     }
00227 
00238     explicit LocalPointer(std::unique_ptr<T> &&p)
00239         : LocalPointerBase<T>(p.release()) {}
00240 
00245     ~LocalPointer() {
00246         delete LocalPointerBase<T>::ptr;
00247     }
00255     LocalPointer<T> &operator=(LocalPointer<T> &&src) noexcept {
00256         delete LocalPointerBase<T>::ptr;
00257         LocalPointerBase<T>::ptr=src.ptr;
00258         src.ptr=nullptr;
00259         return *this;
00260     }
00261 
00270     LocalPointer<T> &operator=(std::unique_ptr<T> &&p) noexcept {
00271         adoptInstead(p.release());
00272         return *this;
00273     }
00274 
00280     void swap(LocalPointer<T> &other) noexcept {
00281         T *temp=LocalPointerBase<T>::ptr;
00282         LocalPointerBase<T>::ptr=other.ptr;
00283         other.ptr=temp;
00284     }
00291     friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) noexcept {
00292         p1.swap(p2);
00293     }
00300     void adoptInstead(T *p) {
00301         delete LocalPointerBase<T>::ptr;
00302         LocalPointerBase<T>::ptr=p;
00303     }
00319     void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
00320         if(U_SUCCESS(errorCode)) {
00321             delete LocalPointerBase<T>::ptr;
00322             LocalPointerBase<T>::ptr=p;
00323             if(p==nullptr) {
00324                 errorCode=U_MEMORY_ALLOCATION_ERROR;
00325             }
00326         } else {
00327             delete p;
00328         }
00329     }
00330 
00342     operator std::unique_ptr<T> () && {
00343         return std::unique_ptr<T>(LocalPointerBase<T>::orphan());
00344     }
00345 };
00346 
00365 template<typename T>
00366 class LocalArray : public LocalPointerBase<T> {
00367 public:
00368     using LocalPointerBase<T>::operator*;
00369     using LocalPointerBase<T>::operator->;
00375     explicit LocalArray(T *p=nullptr) : LocalPointerBase<T>(p) {}
00389     LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
00390         if(p==nullptr && U_SUCCESS(errorCode)) {
00391             errorCode=U_MEMORY_ALLOCATION_ERROR;
00392         }
00393     }
00399     LocalArray(LocalArray<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
00400         src.ptr=nullptr;
00401     }
00402 
00413     explicit LocalArray(std::unique_ptr<T[]> &&p)
00414         : LocalPointerBase<T>(p.release()) {}
00415 
00420     ~LocalArray() {
00421         delete[] LocalPointerBase<T>::ptr;
00422     }
00430     LocalArray<T> &operator=(LocalArray<T> &&src) noexcept {
00431         delete[] LocalPointerBase<T>::ptr;
00432         LocalPointerBase<T>::ptr=src.ptr;
00433         src.ptr=nullptr;
00434         return *this;
00435     }
00436 
00445     LocalArray<T> &operator=(std::unique_ptr<T[]> &&p) noexcept {
00446         adoptInstead(p.release());
00447         return *this;
00448     }
00449 
00455     void swap(LocalArray<T> &other) noexcept {
00456         T *temp=LocalPointerBase<T>::ptr;
00457         LocalPointerBase<T>::ptr=other.ptr;
00458         other.ptr=temp;
00459     }
00466     friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) noexcept {
00467         p1.swap(p2);
00468     }
00475     void adoptInstead(T *p) {
00476         delete[] LocalPointerBase<T>::ptr;
00477         LocalPointerBase<T>::ptr=p;
00478     }
00494     void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
00495         if(U_SUCCESS(errorCode)) {
00496             delete[] LocalPointerBase<T>::ptr;
00497             LocalPointerBase<T>::ptr=p;
00498             if(p==nullptr) {
00499                 errorCode=U_MEMORY_ALLOCATION_ERROR;
00500             }
00501         } else {
00502             delete[] p;
00503         }
00504     }
00512     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
00513 
00525     operator std::unique_ptr<T[]> () && {
00526         return std::unique_ptr<T[]>(LocalPointerBase<T>::orphan());
00527     }
00528 };
00529 
00550 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
00551     class LocalPointerClassName : public LocalPointerBase<Type> { \
00552     public: \
00553         using LocalPointerBase<Type>::operator*; \
00554         using LocalPointerBase<Type>::operator->; \
00555         explicit LocalPointerClassName(Type *p=nullptr) : LocalPointerBase<Type>(p) {} \
00556         LocalPointerClassName(LocalPointerClassName &&src) noexcept \
00557                 : LocalPointerBase<Type>(src.ptr) { \
00558             src.ptr=nullptr; \
00559         } \
00560         /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
00561         explicit LocalPointerClassName(std::unique_ptr<Type, decltype(&closeFunction)> &&p) \
00562                 : LocalPointerBase<Type>(p.release()) {} \
00563         ~LocalPointerClassName() { if (ptr != nullptr) { closeFunction(ptr); } } \
00564         LocalPointerClassName &operator=(LocalPointerClassName &&src) noexcept { \
00565             if (ptr != nullptr) { closeFunction(ptr); } \
00566             LocalPointerBase<Type>::ptr=src.ptr; \
00567             src.ptr=nullptr; \
00568             return *this; \
00569         } \
00570         /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
00571         LocalPointerClassName &operator=(std::unique_ptr<Type, decltype(&closeFunction)> &&p) { \
00572             adoptInstead(p.release()); \
00573             return *this; \
00574         } \
00575         void swap(LocalPointerClassName &other) noexcept { \
00576             Type *temp=LocalPointerBase<Type>::ptr; \
00577             LocalPointerBase<Type>::ptr=other.ptr; \
00578             other.ptr=temp; \
00579         } \
00580         friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) noexcept { \
00581             p1.swap(p2); \
00582         } \
00583         void adoptInstead(Type *p) { \
00584             if (ptr != nullptr) { closeFunction(ptr); } \
00585             ptr=p; \
00586         } \
00587         operator std::unique_ptr<Type, decltype(&closeFunction)> () && { \
00588             return std::unique_ptr<Type, decltype(&closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction); \
00589         } \
00590     }
00591 
00592 U_NAMESPACE_END
00593 
00594 #endif  /* U_SHOW_CPLUSPLUS_API */
00595 #endif  /* __LOCALPOINTER_H__ */