[PATCH] Add conversions between OwningPtr<T> and std::unique_ptr<T>.

Ahmed Charles acharles at outlook.com
Sat Mar 1 15:45:56 PST 2014


Hi chandlerc,

Note: The implicit conversion from OwningPtr<T> to std::unique_ptr<T>
requires rvalue references for this support in the compiler to avoid
moving from an lvalue OwningPtr<T>. To work around this, take_unique is
available, which returns a std::unique_ptr<T>.

std::unique_ptr<T> supports conversions to/from other other types as well
as configurable deletion. Neither of these is supported by OwningPtr<T>,
and thus are not supported by this change.

http://llvm-reviews.chandlerc.com/D2910

Files:
  include/llvm/ADT/OwningPtr.h
  unittests/ADT/OwningPtrTest.cpp

Index: include/llvm/ADT/OwningPtr.h
===================================================================
--- include/llvm/ADT/OwningPtr.h
+++ include/llvm/ADT/OwningPtr.h
@@ -17,6 +17,7 @@
 #include "llvm/Support/Compiler.h"
 #include <cassert>
 #include <cstddef>
+#include <memory>
 
 namespace llvm {
 
@@ -39,6 +40,19 @@
     return *this;
   }
 
+  OwningPtr(std::unique_ptr<T> &&Other) : Ptr(Other.release()) {}
+
+  OwningPtr &operator=(std::unique_ptr<T> &&Other) {
+    reset(Other.release());
+    return *this;
+  }
+
+#if LLVM_HAS_RVALUE_REFERENCE_THIS && 0
+  operator std::unique_ptr<T>() && {
+    return std::unique_ptr<T>(take());
+  }
+#endif
+
   ~OwningPtr() {
     delete Ptr;
   }
@@ -61,6 +75,10 @@
     return Tmp;
   }
 
+  std::unique_ptr<T> take_unique() {
+    return std::unique_ptr<T>(take());
+  }
+
   T &operator*() const {
     assert(Ptr && "Cannot dereference null pointer");
     return *Ptr;
Index: unittests/ADT/OwningPtrTest.cpp
===================================================================
--- unittests/ADT/OwningPtrTest.cpp
+++ unittests/ADT/OwningPtrTest.cpp
@@ -178,5 +178,84 @@
   EXPECT_EQ(2u, TrackDestructor::Destructions);
 }
 
+TEST_F(OwningPtrTest, UniqueToOwningConstruction) {
+  TrackDestructor::ResetCounts();
+  {
+    std::unique_ptr<TrackDestructor> A(new TrackDestructor(3));
+    OwningPtr<TrackDestructor> B = std::move(A);
+    EXPECT_FALSE(A);
+    EXPECT_TRUE(!A);
+    EXPECT_FALSE(A.get());
+    EXPECT_TRUE(B);
+    EXPECT_FALSE(!B);
+    EXPECT_TRUE(B.get());
+    EXPECT_TRUE(B.isValid());
+    EXPECT_EQ(3, (*B).val);
+    EXPECT_EQ(3, B->val);
+    EXPECT_EQ(0u, TrackDestructor::Destructions);
+  }
+  EXPECT_EQ(1u, TrackDestructor::Destructions);
+}
+
+TEST_F(OwningPtrTest, UniqueToOwningAssignment) {
+  TrackDestructor::ResetCounts();
+  {
+    std::unique_ptr<TrackDestructor> A(new TrackDestructor(3));
+    OwningPtr<TrackDestructor> B(new TrackDestructor(4));
+    B = std::move(A);
+    EXPECT_FALSE(A);
+    EXPECT_TRUE(!A);
+    EXPECT_FALSE(A.get());
+    EXPECT_TRUE(B);
+    EXPECT_FALSE(!B);
+    EXPECT_TRUE(B.get());
+    EXPECT_TRUE(B.isValid());
+    EXPECT_EQ(3, (*B).val);
+    EXPECT_EQ(3, B->val);
+    EXPECT_EQ(1u, TrackDestructor::Destructions);
+  }
+  EXPECT_EQ(2u, TrackDestructor::Destructions);
+}
+
+TEST_F(OwningPtrTest, TakeUniqueConstruction) {
+  TrackDestructor::ResetCounts();
+  {
+    OwningPtr<TrackDestructor> A(new TrackDestructor(3));
+    std::unique_ptr<TrackDestructor> B = A.take_unique();
+    EXPECT_FALSE(A);
+    EXPECT_TRUE(!A);
+    EXPECT_FALSE(A.get());
+    EXPECT_FALSE(A.isValid());
+    EXPECT_TRUE(B);
+    EXPECT_FALSE(!B);
+    EXPECT_TRUE(B.get());
+    EXPECT_EQ(3, (*B).val);
+    EXPECT_EQ(3, B->val);
+    EXPECT_EQ(0u, TrackDestructor::Destructions);
+  }
+  EXPECT_EQ(1u, TrackDestructor::Destructions);
+}
+
+#if LLVM_HAS_RVALUE_REFERENCE_THIS && 0
+TEST_F(OwningPtrTest, OwningToUniqueConstruction) {
+  TrackDestructor::ResetCounts();
+  {
+    OwningPtr<TrackDestructor> A(new TrackDestructor(3));
+    std::unique_ptr<TrackDestructor> B = std::move(A);
+    EXPECT_FALSE(A);
+    EXPECT_TRUE(!A);
+    EXPECT_FALSE(A.get());
+    EXPECT_FALSE(A.isValid());
+    EXPECT_TRUE(B);
+    EXPECT_FALSE(!B);
+    EXPECT_TRUE(B.get());
+    EXPECT_EQ(3, (*B).val);
+    EXPECT_EQ(3, B->val);
+    EXPECT_EQ(0u, TrackDestructor::Destructions);
+  }
+  EXPECT_EQ(1u, TrackDestructor::Destructions);
+}
+#endif
+
 } // end anonymous namespace
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2910.1.patch
Type: text/x-patch
Size: 3487 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140301/62429c70/attachment.bin>


More information about the llvm-commits mailing list