1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 2009-2016, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
10 * file name: localpointer.h
12 * tab size: 8 (not used)
15 * created on: 2009nov13
16 * created by: Markus W. Scherer
19 #ifndef __LOCALPOINTER_H__
20 #define __LOCALPOINTER_H__
24 * \brief C++ API: "Smart pointers" for use with and in ICU4C C++ code.
26 * These classes are inspired by
28 * - boost::scoped_ptr & boost::scoped_array
29 * - Taligent Safe Pointers (TOnlyPointerTo)
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.
38 * For details see http://site.icu-project.org/design/cpp/scoped_ptr
41 #include "unicode/utypes.h"
43 #if U_SHOW_CPLUSPLUS_API
50 * "Smart pointer" base class; do not use directly: use LocalPointer etc.
52 * Base class for smart pointer classes that do not throw exceptions.
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().
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).
64 * @see U_DEFINE_LOCAL_OPEN_POINTER
68 class LocalPointerBase
{
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 #if U_HAVE_PLACEMENT_NEW
74 static void* U_EXPORT2
operator new(size_t, void*) = delete;
78 * Constructor takes ownership.
79 * @param p simple pointer to an object that is adopted
82 explicit LocalPointerBase(T
*p
=NULL
) : ptr(p
) {}
84 * Destructor deletes the object it owns.
85 * Subclass must override: Base class does nothing.
88 ~LocalPointerBase() { /* delete ptr; */ }
91 * @return TRUE if ==NULL
94 UBool
isNull() const { return ptr
==NULL
; }
97 * @return TRUE if !=NULL
100 UBool
isValid() const { return ptr
!=NULL
; }
102 * Comparison with a simple pointer, so that existing code
103 * with ==NULL need not be changed.
104 * @param other simple pointer for comparison
105 * @return true if this pointer value equals other
108 bool operator==(const T
*other
) const { return ptr
==other
; }
110 * Comparison with a simple pointer, so that existing code
111 * with !=NULL need not be changed.
112 * @param other simple pointer for comparison
113 * @return true if this pointer value differs from other
116 bool operator!=(const T
*other
) const { return ptr
!=other
; }
118 * Access without ownership change.
119 * @return the pointer value
122 T
*getAlias() const { return ptr
; }
124 * Access without ownership change.
125 * @return the pointer value as a reference
128 T
&operator*() const { return *ptr
; }
130 * Access without ownership change.
131 * @return the pointer value
134 T
*operator->() const { return ptr
; }
136 * Gives up ownership; the internal pointer becomes NULL.
137 * @return the pointer value;
138 * caller becomes responsible for deleting the object
147 * Deletes the object it owns,
148 * and adopts (takes ownership of) the one passed in.
149 * Subclass must override: Base class does not delete the object.
150 * @param p simple pointer to an object that is adopted
153 void adoptInstead(T
*p
) {
164 // No comparison operators with other LocalPointerBases.
165 bool operator==(const LocalPointerBase
<T
> &other
);
166 bool operator!=(const LocalPointerBase
<T
> &other
);
167 // No ownership sharing: No copy constructor, no assignment operator.
168 LocalPointerBase(const LocalPointerBase
<T
> &other
);
169 void operator=(const LocalPointerBase
<T
> &other
);
173 * "Smart pointer" class, deletes objects via the standard C++ delete operator.
174 * For most methods see the LocalPointerBase base class.
178 * LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005));
179 * int32_t length=s->length(); // 2
180 * char16_t lead=s->charAt(0); // 0xd900
181 * if(some condition) { return; } // no need to explicitly delete the pointer
182 * s.adoptInstead(new UnicodeString((char16_t)0xfffc));
183 * length=s->length(); // 1
184 * // no need to explicitly delete the pointer
187 * @see LocalPointerBase
191 class LocalPointer
: public LocalPointerBase
<T
> {
193 using LocalPointerBase
<T
>::operator*;
194 using LocalPointerBase
<T
>::operator->;
196 * Constructor takes ownership.
197 * @param p simple pointer to an object that is adopted
200 explicit LocalPointer(T
*p
=NULL
) : LocalPointerBase
<T
>(p
) {}
202 * Constructor takes ownership and reports an error if NULL.
204 * This constructor is intended to be used with other-class constructors
205 * that may report a failure UErrorCode,
206 * so that callers need to check only for U_FAILURE(errorCode)
207 * and not also separately for isNull().
209 * @param p simple pointer to an object that is adopted
210 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
211 * if p==NULL and no other failure code had been set
214 LocalPointer(T
*p
, UErrorCode
&errorCode
) : LocalPointerBase
<T
>(p
) {
215 if(p
==NULL
&& U_SUCCESS(errorCode
)) {
216 errorCode
=U_MEMORY_ALLOCATION_ERROR
;
220 * Move constructor, leaves src with isNull().
221 * @param src source smart pointer
224 LocalPointer(LocalPointer
<T
> &&src
) U_NOEXCEPT
: LocalPointerBase
<T
>(src
.ptr
) {
228 #ifndef U_HIDE_DRAFT_API
230 * Constructs a LocalPointer from a C++11 std::unique_ptr.
231 * The LocalPointer steals the object owned by the std::unique_ptr.
233 * This constructor works via move semantics. If your std::unique_ptr is
234 * in a local variable, you must use std::move.
236 * @param p The std::unique_ptr from which the pointer will be stolen.
239 explicit LocalPointer(std::unique_ptr
<T
> &&p
)
240 : LocalPointerBase
<T
>(p
.release()) {}
241 #endif /* U_HIDE_DRAFT_API */
244 * Destructor deletes the object it owns.
248 delete LocalPointerBase
<T
>::ptr
;
251 * Move assignment operator, leaves src with isNull().
252 * The behavior is undefined if *this and src are the same object.
253 * @param src source smart pointer
257 LocalPointer
<T
> &operator=(LocalPointer
<T
> &&src
) U_NOEXCEPT
{
258 delete LocalPointerBase
<T
>::ptr
;
259 LocalPointerBase
<T
>::ptr
=src
.ptr
;
264 #ifndef U_HIDE_DRAFT_API
266 * Move-assign from an std::unique_ptr to this LocalPointer.
267 * Steals the pointer from the std::unique_ptr.
269 * @param p The std::unique_ptr from which the pointer will be stolen.
273 LocalPointer
<T
> &operator=(std::unique_ptr
<T
> &&p
) U_NOEXCEPT
{
274 adoptInstead(p
.release());
277 #endif /* U_HIDE_DRAFT_API */
281 * @param other other smart pointer
284 void swap(LocalPointer
<T
> &other
) U_NOEXCEPT
{
285 T
*temp
=LocalPointerBase
<T
>::ptr
;
286 LocalPointerBase
<T
>::ptr
=other
.ptr
;
290 * Non-member LocalPointer swap function.
291 * @param p1 will get p2's pointer
292 * @param p2 will get p1's pointer
295 friend inline void swap(LocalPointer
<T
> &p1
, LocalPointer
<T
> &p2
) U_NOEXCEPT
{
299 * Deletes the object it owns,
300 * and adopts (takes ownership of) the one passed in.
301 * @param p simple pointer to an object that is adopted
304 void adoptInstead(T
*p
) {
305 delete LocalPointerBase
<T
>::ptr
;
306 LocalPointerBase
<T
>::ptr
=p
;
309 * Deletes the object it owns,
310 * and adopts (takes ownership of) the one passed in.
312 * If U_FAILURE(errorCode), then the current object is retained and the new one deleted.
314 * If U_SUCCESS(errorCode) but the input pointer is NULL,
315 * then U_MEMORY_ALLOCATION_ERROR is set,
316 * the current object is deleted, and NULL is set.
318 * @param p simple pointer to an object that is adopted
319 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
320 * if p==NULL and no other failure code had been set
323 void adoptInsteadAndCheckErrorCode(T
*p
, UErrorCode
&errorCode
) {
324 if(U_SUCCESS(errorCode
)) {
325 delete LocalPointerBase
<T
>::ptr
;
326 LocalPointerBase
<T
>::ptr
=p
;
328 errorCode
=U_MEMORY_ALLOCATION_ERROR
;
335 #ifndef U_HIDE_DRAFT_API
337 * Conversion operator to a C++11 std::unique_ptr.
338 * Disowns the object and gives it to the returned std::unique_ptr.
340 * This operator works via move semantics. If your LocalPointer is
341 * in a local variable, you must use std::move.
343 * @return An std::unique_ptr owning the pointer previously owned by this
347 operator std::unique_ptr
<T
> () && {
348 return std::unique_ptr
<T
>(LocalPointerBase
<T
>::orphan());
350 #endif /* U_HIDE_DRAFT_API */
354 * "Smart pointer" class, deletes objects via the C++ array delete[] operator.
355 * For most methods see the LocalPointerBase base class.
356 * Adds operator[] for array item access.
360 * LocalArray<UnicodeString> a(new UnicodeString[2]);
361 * a[0].append((char16_t)0x61);
362 * if(some condition) { return; } // no need to explicitly delete the array
363 * a.adoptInstead(new UnicodeString[4]);
364 * a[3].append((char16_t)0x62).append((char16_t)0x63).reverse();
365 * // no need to explicitly delete the array
368 * @see LocalPointerBase
372 class LocalArray
: public LocalPointerBase
<T
> {
374 using LocalPointerBase
<T
>::operator*;
375 using LocalPointerBase
<T
>::operator->;
377 * Constructor takes ownership.
378 * @param p simple pointer to an array of T objects that is adopted
381 explicit LocalArray(T
*p
=NULL
) : LocalPointerBase
<T
>(p
) {}
383 * Constructor takes ownership and reports an error if NULL.
385 * This constructor is intended to be used with other-class constructors
386 * that may report a failure UErrorCode,
387 * so that callers need to check only for U_FAILURE(errorCode)
388 * and not also separately for isNull().
390 * @param p simple pointer to an array of T objects that is adopted
391 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
392 * if p==NULL and no other failure code had been set
395 LocalArray(T
*p
, UErrorCode
&errorCode
) : LocalPointerBase
<T
>(p
) {
396 if(p
==NULL
&& U_SUCCESS(errorCode
)) {
397 errorCode
=U_MEMORY_ALLOCATION_ERROR
;
401 * Move constructor, leaves src with isNull().
402 * @param src source smart pointer
405 LocalArray(LocalArray
<T
> &&src
) U_NOEXCEPT
: LocalPointerBase
<T
>(src
.ptr
) {
409 #ifndef U_HIDE_DRAFT_API
411 * Constructs a LocalArray from a C++11 std::unique_ptr of an array type.
412 * The LocalPointer steals the array owned by the std::unique_ptr.
414 * This constructor works via move semantics. If your std::unique_ptr is
415 * in a local variable, you must use std::move.
417 * @param p The std::unique_ptr from which the array will be stolen.
420 explicit LocalArray(std::unique_ptr
<T
[]> &&p
)
421 : LocalPointerBase
<T
>(p
.release()) {}
422 #endif /* U_HIDE_DRAFT_API */
425 * Destructor deletes the array it owns.
429 delete[] LocalPointerBase
<T
>::ptr
;
432 * Move assignment operator, leaves src with isNull().
433 * The behavior is undefined if *this and src are the same object.
434 * @param src source smart pointer
438 LocalArray
<T
> &operator=(LocalArray
<T
> &&src
) U_NOEXCEPT
{
439 delete[] LocalPointerBase
<T
>::ptr
;
440 LocalPointerBase
<T
>::ptr
=src
.ptr
;
445 #ifndef U_HIDE_DRAFT_API
447 * Move-assign from an std::unique_ptr to this LocalPointer.
448 * Steals the array from the std::unique_ptr.
450 * @param p The std::unique_ptr from which the array will be stolen.
454 LocalArray
<T
> &operator=(std::unique_ptr
<T
[]> &&p
) U_NOEXCEPT
{
455 adoptInstead(p
.release());
458 #endif /* U_HIDE_DRAFT_API */
462 * @param other other smart pointer
465 void swap(LocalArray
<T
> &other
) U_NOEXCEPT
{
466 T
*temp
=LocalPointerBase
<T
>::ptr
;
467 LocalPointerBase
<T
>::ptr
=other
.ptr
;
471 * Non-member LocalArray swap function.
472 * @param p1 will get p2's pointer
473 * @param p2 will get p1's pointer
476 friend inline void swap(LocalArray
<T
> &p1
, LocalArray
<T
> &p2
) U_NOEXCEPT
{
480 * Deletes the array it owns,
481 * and adopts (takes ownership of) the one passed in.
482 * @param p simple pointer to an array of T objects that is adopted
485 void adoptInstead(T
*p
) {
486 delete[] LocalPointerBase
<T
>::ptr
;
487 LocalPointerBase
<T
>::ptr
=p
;
490 * Deletes the array it owns,
491 * and adopts (takes ownership of) the one passed in.
493 * If U_FAILURE(errorCode), then the current array is retained and the new one deleted.
495 * If U_SUCCESS(errorCode) but the input pointer is NULL,
496 * then U_MEMORY_ALLOCATION_ERROR is set,
497 * the current array is deleted, and NULL is set.
499 * @param p simple pointer to an array of T objects that is adopted
500 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
501 * if p==NULL and no other failure code had been set
504 void adoptInsteadAndCheckErrorCode(T
*p
, UErrorCode
&errorCode
) {
505 if(U_SUCCESS(errorCode
)) {
506 delete[] LocalPointerBase
<T
>::ptr
;
507 LocalPointerBase
<T
>::ptr
=p
;
509 errorCode
=U_MEMORY_ALLOCATION_ERROR
;
516 * Array item access (writable).
517 * No index bounds check.
518 * @param i array index
519 * @return reference to the array item
522 T
&operator[](ptrdiff_t i
) const { return LocalPointerBase
<T
>::ptr
[i
]; }
524 #ifndef U_HIDE_DRAFT_API
526 * Conversion operator to a C++11 std::unique_ptr.
527 * Disowns the object and gives it to the returned std::unique_ptr.
529 * This operator works via move semantics. If your LocalPointer is
530 * in a local variable, you must use std::move.
532 * @return An std::unique_ptr owning the pointer previously owned by this
536 operator std::unique_ptr
<T
[]> () && {
537 return std::unique_ptr
<T
[]>(LocalPointerBase
<T
>::orphan());
539 #endif /* U_HIDE_DRAFT_API */
543 * \def U_DEFINE_LOCAL_OPEN_POINTER
544 * "Smart pointer" definition macro, deletes objects via the closeFunction.
545 * Defines a subclass of LocalPointerBase which works just
546 * like LocalPointer<Type> except that this subclass will use the closeFunction
547 * rather than the C++ delete operator.
551 * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
552 * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
553 * utf8Out, (int32_t)sizeof(utf8Out),
554 * utf8In, utf8InLength, &errorCode);
555 * if(U_FAILURE(errorCode)) { return; } // no need to explicitly delete the UCaseMap
558 * @see LocalPointerBase
562 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
563 class LocalPointerClassName : public LocalPointerBase<Type> { \
565 using LocalPointerBase<Type>::operator*; \
566 using LocalPointerBase<Type>::operator->; \
567 explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
568 LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \
569 : LocalPointerBase<Type>(src.ptr) { \
572 /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
573 explicit LocalPointerClassName(std::unique_ptr<Type, decltype(&closeFunction)> &&p) \
574 : LocalPointerBase<Type>(p.release()) {} \
575 ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \
576 LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \
577 if (ptr != NULL) { closeFunction(ptr); } \
578 LocalPointerBase<Type>::ptr=src.ptr; \
582 /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
583 LocalPointerClassName &operator=(std::unique_ptr<Type, decltype(&closeFunction)> &&p) { \
584 adoptInstead(p.release()); \
587 void swap(LocalPointerClassName &other) U_NOEXCEPT { \
588 Type *temp=LocalPointerBase<Type>::ptr; \
589 LocalPointerBase<Type>::ptr=other.ptr; \
592 friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \
595 void adoptInstead(Type *p) { \
596 if (ptr != NULL) { closeFunction(ptr); } \
599 operator std::unique_ptr<Type, decltype(&closeFunction)> () && { \
600 return std::unique_ptr<Type, decltype(&closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction); \
606 #endif /* U_SHOW_CPLUSPLUS_API */
607 #endif /* __LOCALPOINTER_H__ */