ICU-20357 Adding LocalPointer conversion methods to/from std::unique_ptr

- Requires the right side to be an rvalue reference.
- Includes move constructor, move operator, and conversion operator.
This commit is contained in:
Shane Carr 2019-01-24 16:13:04 -08:00 committed by Shane F. Carr
parent 4104d33501
commit b7a3571b21
2 changed files with 102 additions and 0 deletions

View File

@ -42,6 +42,8 @@
#if U_SHOW_CPLUSPLUS_API
#include <memory>
U_NAMESPACE_BEGIN
/**
@ -222,6 +224,17 @@ public:
LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
src.ptr=NULL;
}
/**
* Constructs a LocalPointer from a C++11 std::unique_ptr.
* The LocalPointer steals the object owned by the std::unique_ptr.
*
* This constructor works via move semantics. If your std::unique_ptr is
* in a local variable, you must use std::move.
*
* @param p The std::unique_ptr from which the pointer will be stolen.
* @draft ICU 64
*/
explicit LocalPointer(std::unique_ptr<T> &&p) : LocalPointerBase<T>(p.release()) {}
/**
* Destructor deletes the object it owns.
* @stable ICU 4.4
@ -239,6 +252,18 @@ public:
LocalPointer<T> &operator=(LocalPointer<T> &&src) U_NOEXCEPT {
return moveFrom(src);
}
/**
* Move-assign from an std::unique_ptr to this LocalPointer.
* Steals the pointer from the std::unique_ptr.
*
* @param p The std::unique_ptr from which the pointer will be stolen.
* @return *this
* @draft ICU 64
*/
LocalPointer<T> &operator=(std::unique_ptr<T> &&p) U_NOEXCEPT {
adoptInstead(p.release());
return *this;
}
// do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API
/**
* Move assignment, leaves src with isNull().
@ -310,6 +335,20 @@ public:
delete p;
}
}
/**
* Conversion operator to a C++11 std::unique_ptr.
* Disowns the object and gives it to the returned std::unique_ptr.
*
* This operator works via move semantics. If your LocalPointer is
* in a local variable, you must use std::move.
*
* @return An std::unique_ptr owning the pointer previously owned by this
* icu::LocalPointer.
* @draft ICU 64
*/
operator std::unique_ptr<T> () && {
return std::unique_ptr<T>(LocalPointerBase<T>::orphan());
}
};
/**
@ -367,6 +406,17 @@ public:
LocalArray(LocalArray<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
src.ptr=NULL;
}
/**
* Constructs a LocalArray from a C++11 std::unique_ptr of an array type.
* The LocalPointer steals the array owned by the std::unique_ptr.
*
* This constructor works via move semantics. If your std::unique_ptr is
* in a local variable, you must use std::move.
*
* @param p The std::unique_ptr from which the array will be stolen.
* @draft ICU 64
*/
explicit LocalArray(std::unique_ptr<T[]> &&p) : LocalPointerBase<T>(p.release()) {}
/**
* Destructor deletes the array it owns.
* @stable ICU 4.4
@ -384,6 +434,18 @@ public:
LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT {
return moveFrom(src);
}
/**
* Move-assign from an std::unique_ptr to this LocalPointer.
* Steals the array from the std::unique_ptr.
*
* @param p The std::unique_ptr from which the array will be stolen.
* @return *this
* @draft ICU 64
*/
LocalArray<T> &operator=(std::unique_ptr<T[]> &&p) U_NOEXCEPT {
adoptInstead(p.release());
return *this;
}
// do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API
/**
* Move assignment, leaves src with isNull().
@ -463,6 +525,20 @@ public:
* @stable ICU 4.4
*/
T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
/**
* Conversion operator to a C++11 std::unique_ptr.
* Disowns the object and gives it to the returned std::unique_ptr.
*
* This operator works via move semantics. If your LocalPointer is
* in a local variable, you must use std::move.
*
* @return An std::unique_ptr owning the pointer previously owned by this
* icu::LocalPointer.
* @draft ICU 64
*/
operator std::unique_ptr<T[]> () && {
return std::unique_ptr<T[]>(LocalPointerBase<T>::orphan());
}
};
/**

View File

@ -385,8 +385,10 @@ public:
void TestLocalPointer();
void TestLocalPointerMoveSwap();
void TestLocalPointerStdUniquePtr();
void TestLocalArray();
void TestLocalArrayMoveSwap();
void TestLocalArrayStdUniquePtr();
void TestLocalXyzPointer();
void TestLocalXyzPointerMoveSwap();
void TestLocalXyzPointerNull();
@ -403,8 +405,10 @@ void LocalPointerTest::runIndexedTest(int32_t index, UBool exec, const char *&na
TESTCASE_AUTO_BEGIN;
TESTCASE_AUTO(TestLocalPointer);
TESTCASE_AUTO(TestLocalPointerMoveSwap);
TESTCASE_AUTO(TestLocalPointerStdUniquePtr);
TESTCASE_AUTO(TestLocalArray);
TESTCASE_AUTO(TestLocalArrayMoveSwap);
TESTCASE_AUTO(TestLocalArrayStdUniquePtr);
TESTCASE_AUTO(TestLocalXyzPointer);
TESTCASE_AUTO(TestLocalXyzPointerMoveSwap);
TESTCASE_AUTO(TestLocalXyzPointerNull);
@ -514,6 +518,17 @@ void LocalPointerTest::TestLocalPointerMoveSwap() {
s3.moveFrom(s3);
}
void LocalPointerTest::TestLocalPointerStdUniquePtr() {
// Implicit conversion operator
std::unique_ptr<UnicodeString> s = LocalPointer<UnicodeString>(new UnicodeString((UChar32)0x50005));
// Explicit move constructor
LocalPointer<UnicodeString> s2(std::move(s));
// Conversion operator should also work with std::move
s = std::move(s2);
// Back again with move assignment
s2 = std::move(s);
}
// Exercise almost every LocalArray method (but not LocalPointerBase).
void LocalPointerTest::TestLocalArray() {
// constructor
@ -607,6 +622,17 @@ void LocalPointerTest::TestLocalArrayMoveSwap() {
a3.moveFrom(a3);
}
void LocalPointerTest::TestLocalArrayStdUniquePtr() {
// Implicit conversion operator
std::unique_ptr<UnicodeString[]> a = LocalArray<UnicodeString>(new UnicodeString[2]);
// Explicit move constructor
LocalArray<UnicodeString> a2(std::move(a));
// Conversion operator should also work with std::move
a = std::move(a2);
// Back again with move assignment
a2 = std::move(a);
}
#include "unicode/ucnvsel.h"
#include "unicode/ucal.h"
#include "unicode/udatpg.h"