Add nonstd::unique_ptr move assigment operator.
authorTom Sepez <tsepez@chromium.org>
Tue, 22 Sep 2015 22:06:59 +0000 (15:06 -0700)
committerTom Sepez <tsepez@chromium.org>
Tue, 22 Sep 2015 22:06:59 +0000 (15:06 -0700)
std::unique_ptr supports move assignment as in:
  ptr2 = std::move(ptr1);

R=jyasskin@chromium.org

Review URL: https://codereview.chromium.org/1358163002 .

pdfium.gyp
third_party/base/nonstd_unique_ptr.h
third_party/base/nonstd_unique_ptr_unittest.cpp [new file with mode: 0644]

index 12314d7..d62cd56 100644 (file)
         'core/src/fxcrt/fx_system_unittest.cpp',
         'testing/fx_string_testhelpers.h',
         'testing/fx_string_testhelpers.cpp',
+        'third_party/base/nonstd_unique_ptr_unittest.cpp',
       ],
     },
     {
index 1d1c43f..d666e1e 100644 (file)
@@ -176,6 +176,13 @@ class unique_ptr : public unique_ptr_base<C> {
     }
   }
 
+  // Move assignment.
+  unique_ptr<C>& operator=(unique_ptr<C>&& that) {
+    if (that.ptr_ != ptr_)
+      reset(that.release());
+    return *this;
+  }
+
 private:
   // Forbid comparison of unique_ptr types.  If C2 != C, it totally doesn't
   // make sense, and if C2 == C, it still doesn't make sense because you should
@@ -222,6 +229,13 @@ class unique_ptr<C[]> : public unique_ptr_base<C> {
     }
   }
 
+  // Move assignment.
+  unique_ptr<C>& operator=(unique_ptr<C>&& that) {
+    if (that.ptr_ != ptr_)
+      reset(that.release());
+    return *this;
+  }
+
   // Support indexing since it is holding array.
   C& operator[] (size_t i) { return ptr_[i]; }
 
diff --git a/third_party/base/nonstd_unique_ptr_unittest.cpp b/third_party/base/nonstd_unique_ptr_unittest.cpp
new file mode 100644 (file)
index 0000000..49cc901
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright 2015 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <sstream>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "macros.h"
+#include "nonstd_unique_ptr.h"
+
+using nonstd::unique_ptr;
+
+namespace {
+
+// Used to test depth subtyping.
+class CtorDtorLoggerParent {
+ public:
+  virtual ~CtorDtorLoggerParent() {}
+
+  virtual void SetPtr(int* ptr) = 0;
+
+  virtual int SomeMeth(int x) const = 0;
+};
+
+class CtorDtorLogger : public CtorDtorLoggerParent {
+ public:
+  CtorDtorLogger() : ptr_(nullptr) {}
+  explicit CtorDtorLogger(int* ptr) { SetPtr(ptr); }
+  ~CtorDtorLogger() override { --*ptr_; }
+
+  void SetPtr(int* ptr) override {
+    ptr_ = ptr;
+    ++*ptr_;
+  }
+
+  int SomeMeth(int x) const override { return x; }
+
+ private:
+  int* ptr_;
+
+  // Disallow evil constructors.
+  CtorDtorLogger(const CtorDtorLogger&) = delete;
+  void operator=(const CtorDtorLogger&) = delete;
+};
+
+struct CountingDeleter {
+  explicit CountingDeleter(int* count) : count_(count) {}
+  inline void operator()(double* ptr) const { (*count_)++; }
+  int* count_;
+};
+
+// Do not delete this function!  It's existence is to test that you can
+// return a temporarily constructed version of the scoper.
+unique_ptr<CtorDtorLogger> TestReturnOfType(int* constructed) {
+  return unique_ptr<CtorDtorLogger>(new CtorDtorLogger(constructed));
+}
+
+}  // namespace
+
+TEST(UniquePtrTest, MoveTest) {
+  int constructed = 0;
+  int constructed4 = 0;
+  {
+    unique_ptr<CtorDtorLogger> ptr1(new CtorDtorLogger(&constructed));
+    EXPECT_EQ(1, constructed);
+    EXPECT_TRUE(ptr1);
+
+    unique_ptr<CtorDtorLogger> ptr2(nonstd::move(ptr1));
+    EXPECT_EQ(1, constructed);
+    EXPECT_FALSE(ptr1);
+    EXPECT_TRUE(ptr2);
+
+    unique_ptr<CtorDtorLogger> ptr3;
+    ptr3 = nonstd::move(ptr2);
+    EXPECT_EQ(1, constructed);
+    EXPECT_FALSE(ptr2);
+    EXPECT_TRUE(ptr3);
+
+    unique_ptr<CtorDtorLogger> ptr4(new CtorDtorLogger(&constructed4));
+    EXPECT_EQ(1, constructed4);
+    ptr4 = nonstd::move(ptr3);
+    EXPECT_EQ(0, constructed4);
+    EXPECT_FALSE(ptr3);
+    EXPECT_TRUE(ptr4);
+  }
+  EXPECT_EQ(0, constructed);
+}