diff options
author | dcheng <dcheng@chromium.org> | 2015-12-14 12:31:52 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-14 20:33:25 +0000 |
commit | 69f2a0417b06343a0f3241e7d87bd78ca3849ca7 (patch) | |
tree | 395092f0d3debba844a91aeb52b5b34f9dc9b03e /base | |
parent | e1504e2e6888ef6ab7ae7e5760f8688a47d78b72 (diff) | |
download | chromium_src-69f2a0417b06343a0f3241e7d87bd78ca3849ca7.zip chromium_src-69f2a0417b06343a0f3241e7d87bd78ca3849ca7.tar.gz chromium_src-69f2a0417b06343a0f3241e7d87bd78ca3849ca7.tar.bz2 |
Compatibility shim to allow std::unique_ptr use with base::Callback.
BUG=554298,561749
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
Review URL: https://codereview.chromium.org/1494373002
Cr-Commit-Position: refs/heads/master@{#365087}
Diffstat (limited to 'base')
-rw-r--r-- | base/bind_unittest.cc | 48 | ||||
-rw-r--r-- | base/callback_internal.h | 14 |
2 files changed, 60 insertions, 2 deletions
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc index f885403..afa523c 100644 --- a/base/bind_unittest.cc +++ b/base/bind_unittest.cc @@ -4,6 +4,9 @@ #include "base/bind.h" +#include <memory> +#include <utility> + #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" @@ -150,7 +153,7 @@ class DeleteCounter { template <typename T> T PassThru(T scoper) { - return scoper.Pass(); + return scoper; } // Some test functions that we can Bind to. @@ -752,6 +755,49 @@ TEST_F(BindTest, ScopedPtr) { cb_unbound.Run(ptr.Pass()); } +TEST_F(BindTest, UniquePtr) { + int deletes = 0; + + // Tests the Passed() function's support for pointers. + std::unique_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes)); + Callback<std::unique_ptr<DeleteCounter>(void)> unused_callback = + Bind(&PassThru<std::unique_ptr<DeleteCounter>>, Passed(&ptr)); + EXPECT_FALSE(ptr.get()); + EXPECT_EQ(0, deletes); + + // If we never invoke the Callback, it retains ownership and deletes. + unused_callback.Reset(); + EXPECT_EQ(1, deletes); + + // Tests the Passed() function's support for rvalues. + deletes = 0; + DeleteCounter* counter = new DeleteCounter(&deletes); + Callback<std::unique_ptr<DeleteCounter>(void)> callback = + Bind(&PassThru<std::unique_ptr<DeleteCounter>>, + Passed(std::unique_ptr<DeleteCounter>(counter))); + EXPECT_FALSE(ptr.get()); + EXPECT_EQ(0, deletes); + + // Check that ownership can be transferred back out. + std::unique_ptr<DeleteCounter> result = callback.Run(); + ASSERT_EQ(counter, result.get()); + EXPECT_EQ(0, deletes); + + // Resetting does not delete since ownership was transferred. + callback.Reset(); + EXPECT_EQ(0, deletes); + + // Ensure that we actually did get ownership. + result.reset(); + EXPECT_EQ(1, deletes); + + // Test unbound argument forwarding. + Callback<std::unique_ptr<DeleteCounter>(std::unique_ptr<DeleteCounter>)> + cb_unbound = Bind(&PassThru<std::unique_ptr<DeleteCounter>>); + ptr.reset(new DeleteCounter(&deletes)); + cb_unbound.Run(std::move(ptr)); +} + // Argument Copy-constructor usage for non-reference parameters. // - Bound arguments are only copied once. // - Forwarded arguments are only copied once. diff --git a/base/callback_internal.h b/base/callback_internal.h index aa8542c..a2adbf9 100644 --- a/base/callback_internal.h +++ b/base/callback_internal.h @@ -9,6 +9,7 @@ #define BASE_CALLBACK_INTERNAL_H_ #include <stddef.h> +#include <memory> #include <type_traits> #include "base/atomic_ref_count.h" @@ -94,7 +95,13 @@ class BASE_EXPORT CallbackBase { // A helper template to determine if given type is non-const move-only-type, // i.e. if a value of the given type should be passed via std::move() in a -// destructive way. +// destructive way. Types are considered to be move-only if they have a +// sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using +// the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro. +// It would be easy to generalize this trait to all move-only types... but this +// confuses template deduction in VS2013 with certain types such as +// std::unique_ptr. +// TODO(dcheng): Revisit this when Windows switches to VS2015 by default. template <typename T> struct IsMoveOnlyType { template <typename U> static YesType Test(const typename U::MoveOnlyTypeForCPP03*); @@ -106,6 +113,11 @@ template <typename T> struct IsMoveOnlyType { !is_const<T>::value; }; +// Specialization of IsMoveOnlyType so that std::unique_ptr is still considered +// move-only, even without the sentinel member. +template <typename T> +struct IsMoveOnlyType<std::unique_ptr<T>> : std::true_type {}; + template <typename> struct CallbackParamTraitsForMoveOnlyType; |