Commit 2299e91d authored by danakj's avatar danakj Committed by Commit bot

Add nullptr support to scoped_ptr.

This adds support to use nullptr to construct, assign, or return a
scoped_ptr<T> and scoped_ptr<T[]>. Support for this requires the use
of a move-only constructor.

The changes are:

- Add a constructor that takes decltype(nullptr) as a parameter. This
allows behaviour such as scoped_ptr<T>(nullptr), but also allows a
function with return type scoped_ptr<T> to "return nullptr;" instead
of "return scoped_ptr<T>();".

- Add an operator=(decltype(nullptr)) that resets the scoped_ptr to
empty and deletes anything it held.

- Add/Modify a constructor to take a scoped_ptr<U,E>&& parameter for
constructing a scoped_ptr from another using move-only semantics. This
piece is critical for allowing the function returning nullptr to be
assigned to some other scoped_ptr at the callsite. In particular, take
the following code:
  scoped_ptr<T> Function() { return nullptr; }
  scoped_ptr<T> var = Function();
In this case the constructor which takes a nullptr allows Function() to
be written, but not to be used. The move-only constructor allows the
assignment from Function() to var. See "C++11 feature proposal:
Move-only constructors" on chromium-dev for more explanation why.

The scoped_ptr<T> class already had a constructor which took
scoped_ptr<U,E> as an argument, so this was changed to be
scoped_ptr<U,E>&& instead. The scoped_ptr<T[]> class had no such
constructor, so a scoped_ptr&& constructor was added. These match
the constructors found on the unique_ptr class.

- Remove the RValue type and the contructor that constructs a
scoped_ptr from an RValue. Change Pass() to return a scoped_ptr&&
instead of a scoped_ptr::RValue, to avoid the type conversion and
remove some complexity. This is done with a new emulation macro that
still provides Pass() and makes the type go down the MoveOnlyType
path in base::Callback code.

This adds base_unittests to demonstrate and use these changes.

The use of Pass() remains unchanged until std::move() is written
or allowed. At that time std::move() could be used instead of Pass.

R=brettw@chromium.org, jamesr@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#297072}
parent d9875966
This diff is collapsed.
......@@ -406,6 +406,8 @@ TEST(ScopedPtrTest, PassBehavior) {
// Should auto-destruct logger by end of scope.
scoper.Pass();
// This differs from unique_ptr, as Pass() has side effects but std::move()
// does not.
EXPECT_FALSE(scoper.get());
}
EXPECT_EQ(0, constructed);
......@@ -602,3 +604,55 @@ TEST(ScopedPtrTest, OverloadedNewAndDelete) {
EXPECT_EQ(1, OverloadedNewAndDelete::delete_count());
EXPECT_EQ(1, OverloadedNewAndDelete::new_count());
}
scoped_ptr<int> NullIntReturn() {
return nullptr;
}
TEST(ScopedPtrTest, Nullptr) {
scoped_ptr<int> scoper1(nullptr);
scoped_ptr<int> scoper2(new int);
scoper2 = nullptr;
scoped_ptr<int> scoper3(NullIntReturn());
scoped_ptr<int> scoper4 = NullIntReturn();
EXPECT_EQ(nullptr, scoper1.get());
EXPECT_EQ(nullptr, scoper2.get());
EXPECT_EQ(nullptr, scoper3.get());
EXPECT_EQ(nullptr, scoper4.get());
}
scoped_ptr<int[]> NullIntArrayReturn() {
return nullptr;
}
TEST(ScopedPtrTest, NullptrArray) {
scoped_ptr<int[]> scoper1(nullptr);
scoped_ptr<int[]> scoper2(new int);
scoper2 = nullptr;
scoped_ptr<int[]> scoper3(NullIntArrayReturn());
scoped_ptr<int[]> scoper4 = NullIntArrayReturn();
EXPECT_EQ(nullptr, scoper1.get());
EXPECT_EQ(nullptr, scoper2.get());
EXPECT_EQ(nullptr, scoper3.get());
EXPECT_EQ(nullptr, scoper4.get());
}
class Super {};
class Sub : public Super {};
scoped_ptr<Sub> SubClassReturn() {
return make_scoped_ptr(new Sub);
}
TEST(ScopedPtrTest, Conversion) {
scoped_ptr<Sub> sub1(new Sub);
scoped_ptr<Sub> sub2(new Sub);
// Upcast with Pass() works.
scoped_ptr<Super> super1 = sub1.Pass();
super1 = sub2.Pass();
// Upcast with an rvalue works.
scoped_ptr<Super> super2 = SubClassReturn();
super2 = SubClassReturn();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment