Chromium Code Reviews| Index: base/bind_helpers.h |
| diff --git a/base/bind_helpers.h b/base/bind_helpers.h |
| index 24063ad1ce58fd27c5535ec81c294c597db841df..43aa7ea7ac3be702de19790bdf0e64175d3c0735 100644 |
| --- a/base/bind_helpers.h |
| +++ b/base/bind_helpers.h |
| @@ -111,7 +111,7 @@ |
| // scoped_ptr<Foo> f(new Foo()); |
| // |
| // // |cb| is given ownership of Foo(). |f| is now NULL. |
| -// // You can use f.Pass() in place of &f, but it's more verbose. |
| +// // You can use std::move(f) in place of &f, but it's more verbose. |
| // Closure cb = Bind(&TakesOwnership, Passed(&f)); |
| // |
| // // Run was never called so |cb| still owns Foo() and deletes |
| @@ -143,6 +143,9 @@ |
| #ifndef BASE_BIND_HELPERS_H_ |
| #define BASE_BIND_HELPERS_H_ |
| +#include <type_traits> |
| +#include <utility> |
| + |
| #include "base/basictypes.h" |
| #include "base/callback.h" |
| #include "base/memory/weak_ptr.h" |
| @@ -359,22 +362,24 @@ class OwnedWrapper { |
| // created when we are explicitly trying to do a destructive move. |
| // |
| // Two notes: |
| -// 1) PassedWrapper supports any type that has a "Pass()" function. |
| -// This is intentional. The whitelisting of which specific types we |
| -// support is maintained by CallbackParamTraits<>. |
| +// 1) PassedWrapper supports any type that has a move constructor, however |
| +// the type will need to be specifically whitelisted in order for it to be |
| +// bound to a Callback. We guard this explicitly at the call of Passed() |
| +// to make for clear errors. Things not given to Passed() will be forwarded |
| +// and stored by value which will not work for general move-only types. |
| // 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" |
| // scoper to a Callback and allow the Callback to execute once. |
| template <typename T> |
| class PassedWrapper { |
| public: |
| - explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} |
| + explicit PassedWrapper(T&& scoper) |
|
danakj
2015/12/04 20:46:13
This take a T&&, but the T is a class template typ
|
| + : is_valid_(true), scoper_(std::move(scoper)) {} |
| PassedWrapper(const PassedWrapper& other) |
| - : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) { |
| - } |
| + : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} |
| T Pass() const { |
| CHECK(is_valid_); |
| is_valid_ = false; |
| - return scoper_.Pass(); |
| + return std::move(scoper_); |
| } |
| private: |
| @@ -567,16 +572,25 @@ static inline internal::OwnedWrapper<T> Owned(T* o) { |
| } |
| // We offer 2 syntaxes for calling Passed(). The first takes a temporary and |
| -// is best suited for use with the return value of a function. The second |
| -// takes a pointer to the scoper and is just syntactic sugar to avoid having |
| -// to write Passed(scoper.Pass()). |
| -template <typename T> |
| -static inline internal::PassedWrapper<T> Passed(T scoper) { |
| - return internal::PassedWrapper<T>(scoper.Pass()); |
| +// is best suited for use with the return value of a function. The second takes |
| +// a pointer to the scoper and is just syntactic sugar to avoid having to write |
| +// Passed(std::move(scoper)). |
| +// |
| +// Both versions of Passed() prevent T from being an lvalue reference. The first |
| +// via use of enable_if (to prevent reference collapsing from occuring), and the |
| +// second takes a T* which makes it illegal for T to be a reference. |
| +template <typename T, |
| + typename std::enable_if<!std::is_lvalue_reference<T>::value && |
| + internal::IsMoveOnlyType<T>::value>::type* = |
| + nullptr> |
| +static inline internal::PassedWrapper<T> Passed(T&& scoper) { |
|
danakj
2015/12/04 20:46:13
This one doesn't prevent any move constructors (I
danakj
2015/12/04 20:50:16
I thought about this some more and I don't think I
dcheng
2015/12/04 20:59:08
I think what you're seeing is copy elision. Is the
danakj
2015/12/04 21:05:25
Oh, nope. It saves a move constructor to use T&& h
|
| + return internal::PassedWrapper<T>(std::move(scoper)); |
| } |
| -template <typename T> |
| +template <typename T, |
| + typename std::enable_if<internal::IsMoveOnlyType<T>::value>::type* = |
| + nullptr> |
| static inline internal::PassedWrapper<T> Passed(T* scoper) { |
| - return internal::PassedWrapper<T>(scoper->Pass()); |
| + return internal::PassedWrapper<T>(std::move(*scoper)); |
| } |
| template <typename T> |