]> granicus.if.org Git - icu/commitdiff
ICU-20357 Adding std::unique_ptr conversions to LocalXyzPointer macro.
authorShane F. Carr <shane@unicode.org>
Mon, 28 Jan 2019 09:04:48 +0000 (01:04 -0800)
committerShane F. Carr <shane@unicode.org>
Tue, 29 Jan 2019 05:23:35 +0000 (21:23 -0800)
icu4c/source/common/unicode/localpointer.h
icu4c/source/test/intltest/itutil.cpp

index 8872e05d00449ebaffdc1f90a12ec87a7b1d1fae..b618be9c974598c48a10394c48d22fa3aa724636 100644 (file)
@@ -234,7 +234,8 @@ public:
      * @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()) {}
+    explicit LocalPointer(std::unique_ptr<T> &&p)
+        : LocalPointerBase<T>(p.release()) {}
     /**
      * Destructor deletes the object it owns.
      * @stable ICU 4.4
@@ -416,7 +417,8 @@ public:
      * @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()) {}
+    explicit LocalArray(std::unique_ptr<T[]> &&p)
+        : LocalPointerBase<T>(p.release()) {}
     /**
      * Destructor deletes the array it owns.
      * @stable ICU 4.4
@@ -571,10 +573,18 @@ public:
                 : LocalPointerBase<Type>(src.ptr) { \
             src.ptr=NULL; \
         } \
+        /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
+        explicit LocalPointerClassName(std::unique_ptr<Type, decltype(&closeFunction)> &&p) \
+                : LocalPointerBase<Type>(p.release()) {} \
         ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \
         LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \
             return moveFrom(src); \
         } \
+        /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
+        LocalPointerClassName &operator=(std::unique_ptr<Type, decltype(&closeFunction)> &&p) { \
+            adoptInstead(p.release()); \
+            return *this; \
+        } \
         LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \
             if (ptr != NULL) { closeFunction(ptr); } \
             LocalPointerBase<Type>::ptr=src.ptr; \
@@ -593,6 +603,9 @@ public:
             if (ptr != NULL) { closeFunction(ptr); } \
             ptr=p; \
         } \
+        operator std::unique_ptr<Type, decltype(&closeFunction)> () && { \
+            return std::unique_ptr<Type, decltype(&closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction); \
+        } \
     }
 
 U_NAMESPACE_END
index 038028b30e51edcceef9aa7a99be92c3c7932e99..2edca05df75014ee980455145ac504194c3c2e5c 100644 (file)
@@ -392,6 +392,7 @@ public:
     void TestLocalXyzPointer();
     void TestLocalXyzPointerMoveSwap();
     void TestLocalXyzPointerNull();
+    void TestLocalXyzStdUniquePtr();
 };
 
 static IntlTest *createLocalPointerTest() {
@@ -412,6 +413,7 @@ void LocalPointerTest::runIndexedTest(int32_t index, UBool exec, const char *&na
     TESTCASE_AUTO(TestLocalXyzPointer);
     TESTCASE_AUTO(TestLocalXyzPointerMoveSwap);
     TESTCASE_AUTO(TestLocalXyzPointerNull);
+    TESTCASE_AUTO(TestLocalXyzStdUniquePtr);
     TESTCASE_AUTO_END;
 }
 
@@ -519,14 +521,16 @@ void LocalPointerTest::TestLocalPointerMoveSwap() {
 }
 
 void LocalPointerTest::TestLocalPointerStdUniquePtr() {
+    auto* ptr = new UnicodeString((UChar32)0x50005);
     // Implicit conversion operator
-    std::unique_ptr<UnicodeString> s = LocalPointer<UnicodeString>(new UnicodeString((UChar32)0x50005));
+    std::unique_ptr<UnicodeString> s = LocalPointer<UnicodeString>(ptr);
     // 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);
+    assertTrue("Pointer should remain the same", ptr == s2.getAlias());
 }
 
 // Exercise almost every LocalArray method (but not LocalPointerBase).
@@ -623,14 +627,16 @@ void LocalPointerTest::TestLocalArrayMoveSwap() {
 }
 
 void LocalPointerTest::TestLocalArrayStdUniquePtr() {
+    auto* ptr = new UnicodeString[2];
     // Implicit conversion operator
-    std::unique_ptr<UnicodeString[]> a = LocalArray<UnicodeString>(new UnicodeString[2]);
+    std::unique_ptr<UnicodeString[]> a = LocalArray<UnicodeString>(ptr);
     // 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);
+    assertTrue("Pointer should remain the same", ptr == a2.getAlias());
 }
 
 #include "unicode/ucnvsel.h"
@@ -642,6 +648,7 @@ void LocalPointerTest::TestLocalArrayStdUniquePtr() {
 #include "unicode/unorm2.h"
 #include "unicode/uregex.h"
 #include "unicode/utrans.h"
+#include "unicode/uformattedvalue.h"
 
 // Use LocalXyzPointer types that are not covered elsewhere in the intltest suite.
 void LocalPointerTest::TestLocalXyzPointer() {
@@ -864,6 +871,23 @@ void LocalPointerTest::TestLocalXyzPointerNull() {
 
 }
 
+void LocalPointerTest::TestLocalXyzStdUniquePtr() {
+    IcuTestErrorCode status(*this, "TestLocalXyzStdUniquePtr");
+#if !UCONFIG_NO_FORMATTING
+    auto* ptr = ucfpos_open(status);
+    // Implicit conversion operator
+    std::unique_ptr<UConstrainedFieldPosition, void(*)(UConstrainedFieldPosition*)> a =
+        LocalUConstrainedFieldPositionPointer(ptr);
+    // Explicit move constructor
+    LocalUConstrainedFieldPositionPointer 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);
+    assertTrue("Pointer should remain the same", ptr == a2.getAlias());
+#endif // UCONFIG_NO_FORMATTING
+}
+
 /** EnumSet test **/
 #include "unicode/enumset.h"