]> granicus.if.org Git - icu/commitdiff
ICU-20357 Adding LocalPointer conversion methods to/from std::unique_ptr
authorShane Carr <shane@unicode.org>
Fri, 25 Jan 2019 00:13:04 +0000 (16:13 -0800)
committerShane F. Carr <shane@unicode.org>
Fri, 25 Jan 2019 01:51:07 +0000 (17:51 -0800)
- Requires the right side to be an rvalue reference.
- Includes move constructor, move operator, and conversion operator.

icu4c/source/common/unicode/localpointer.h
icu4c/source/test/intltest/itutil.cpp

index 9ed874b706a1d3ecf5e869c4e8d3803550b04d39..8872e05d00449ebaffdc1f90a12ec87a7b1d1fae 100644 (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());
+    }
 };
 
 /**
index cd1935ab0ec56754a3486132cda839348da8ba8a..038028b30e51edcceef9aa7a99be92c3c7932e99 100644 (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"