summaryrefslogtreecommitdiff
path: root/base/bind_helpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/bind_helpers.h')
-rw-r--r--base/bind_helpers.h168
1 files changed, 90 insertions, 78 deletions
diff --git a/base/bind_helpers.h b/base/bind_helpers.h
index 4068d37108..b97558c4b6 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,14 +143,18 @@
#ifndef BASE_BIND_HELPERS_H_
#define BASE_BIND_HELPERS_H_
+#include <stddef.h>
+
#include <map>
#include <memory>
+#include <type_traits>
+#include <utility>
#include <vector>
-#include "base/basictypes.h"
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
+#include "build/build_config.h"
namespace base {
namespace internal {
@@ -189,7 +193,7 @@ namespace internal {
// want to probe for. Then we create a class Base that inherits from both T
// (the class we wish to probe) and BaseMixin. Note that the function
// signature in BaseMixin does not need to match the signature of the function
-// we are probing for; thus it's easiest to just use void(void).
+// we are probing for; thus it's easiest to just use void().
//
// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an
// ambiguous resolution between BaseMixin and T. This lets us write the
@@ -226,8 +230,8 @@ namespace internal {
// See http://crbug.com/82038.
template <typename T>
class SupportsAddRefAndRelease {
- typedef char Yes[1];
- typedef char No[2];
+ using Yes = char[1];
+ using No = char[2];
struct BaseMixin {
void AddRef();
@@ -246,7 +250,7 @@ class SupportsAddRefAndRelease {
#pragma warning(pop)
#endif
- template <void(BaseMixin::*)(void)> struct Helper {};
+ template <void(BaseMixin::*)()> struct Helper {};
template <typename C>
static No& Check(Helper<&C::AddRef>*);
@@ -280,8 +284,8 @@ struct UnsafeBindtoRefCountedArg<T*>
template <typename T>
class HasIsMethodTag {
- typedef char Yes[1];
- typedef char No[2];
+ using Yes = char[1];
+ using No = char[2];
template <typename U>
static Yes& Check(typename U::IsMethod*);
@@ -363,22 +367,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)
+ : 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:
@@ -450,13 +456,13 @@ class PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>> {
// Unwrap the stored parameters for the wrappers above.
template <typename T>
struct UnwrapTraits {
- typedef const T& ForwardType;
+ using ForwardType = const T&;
static ForwardType Unwrap(const T& o) { return o; }
};
template <typename T>
struct UnwrapTraits<UnretainedWrapper<T> > {
- typedef T* ForwardType;
+ using ForwardType = T*;
static ForwardType Unwrap(UnretainedWrapper<T> unretained) {
return unretained.get();
}
@@ -464,7 +470,7 @@ struct UnwrapTraits<UnretainedWrapper<T> > {
template <typename T>
struct UnwrapTraits<ConstRefWrapper<T> > {
- typedef const T& ForwardType;
+ using ForwardType = const T&;
static ForwardType Unwrap(ConstRefWrapper<T> const_ref) {
return const_ref.get();
}
@@ -472,19 +478,19 @@ struct UnwrapTraits<ConstRefWrapper<T> > {
template <typename T>
struct UnwrapTraits<scoped_refptr<T> > {
- typedef T* ForwardType;
+ using ForwardType = T*;
static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); }
};
template <typename T>
struct UnwrapTraits<WeakPtr<T> > {
- typedef const WeakPtr<T>& ForwardType;
+ using ForwardType = const WeakPtr<T>&;
static ForwardType Unwrap(const WeakPtr<T>& o) { return o; }
};
template <typename T>
struct UnwrapTraits<OwnedWrapper<T> > {
- typedef T* ForwardType;
+ using ForwardType = T*;
static ForwardType Unwrap(const OwnedWrapper<T>& o) {
return o.get();
}
@@ -492,7 +498,7 @@ struct UnwrapTraits<OwnedWrapper<T> > {
template <typename T>
struct UnwrapTraits<PassedWrapper<T> > {
- typedef T ForwardType;
+ using ForwardType = T;
static T Unwrap(PassedWrapper<T>& o) {
return o.Pass();
}
@@ -575,25 +581,50 @@ struct DropTypeListItemImpl<n, TypeList<T, List...>>
template <typename T, typename... List>
struct DropTypeListItemImpl<0, TypeList<T, List...>> {
- typedef TypeList<T, List...> Type;
+ using Type = TypeList<T, List...>;
};
template <>
struct DropTypeListItemImpl<0, TypeList<>> {
- typedef TypeList<> Type;
+ using Type = TypeList<>;
};
// A type-level function that drops |n| list item from given TypeList.
template <size_t n, typename List>
using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type;
+// Used for TakeTypeListItem implementation.
+template <size_t n, typename List, typename... Accum>
+struct TakeTypeListItemImpl;
+
+// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
+template <size_t n, typename T, typename... List, typename... Accum>
+struct TakeTypeListItemImpl<n, TypeList<T, List...>, Accum...>
+ : TakeTypeListItemImpl<n - 1, TypeList<List...>, Accum..., T> {};
+
+template <typename T, typename... List, typename... Accum>
+struct TakeTypeListItemImpl<0, TypeList<T, List...>, Accum...> {
+ using Type = TypeList<Accum...>;
+};
+
+template <typename... Accum>
+struct TakeTypeListItemImpl<0, TypeList<>, Accum...> {
+ using Type = TypeList<Accum...>;
+};
+
+// A type-level function that takes first |n| list item from given TypeList.
+// E.g. TakeTypeListItem<3, TypeList<A, B, C, D>> is evaluated to
+// TypeList<A, B, C>.
+template <size_t n, typename List>
+using TakeTypeListItem = typename TakeTypeListItemImpl<n, List>::Type;
+
// Used for ConcatTypeLists implementation.
template <typename List1, typename List2>
struct ConcatTypeListsImpl;
template <typename... Types1, typename... Types2>
struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> {
- typedef TypeList<Types1..., Types2...> Type;
+ using Type = TypeList<Types1..., Types2...>;
};
// A type-level function that concats two TypeLists.
@@ -606,7 +637,9 @@ struct MakeFunctionTypeImpl;
template <typename R, typename... Args>
struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
- typedef R(Type)(Args...);
+ // MSVC 2013 doesn't support Type Alias of function types.
+ // Revisit this after we update it to newer version.
+ typedef R Type(Args...);
};
// A type-level function that constructs a function type that has |R| as its
@@ -614,6 +647,20 @@ struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
template <typename R, typename ArgList>
using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type;
+// Used for ExtractArgs.
+template <typename Signature>
+struct ExtractArgsImpl;
+
+template <typename R, typename... Args>
+struct ExtractArgsImpl<R(Args...)> {
+ using Type = TypeList<Args...>;
+};
+
+// A type-level function that extracts function arguments into a TypeList.
+// E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>.
+template <typename Signature>
+using ExtractArgs = typename ExtractArgsImpl<Signature>::Type;
+
} // namespace internal
template <typename T>
@@ -631,60 +678,25 @@ static inline internal::OwnedWrapper<T> Owned(T* o) {
return internal::OwnedWrapper<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());
+// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and
+// is best suited for use with the return value of a function or other temporary
+// rvalues. 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, and the second takes a T* which will not bind to T&.
+template <typename T,
+ typename std::enable_if<internal::IsMoveOnlyType<T>::value &&
+ !std::is_lvalue_reference<T>::value>::type* =
+ nullptr>
+static inline internal::PassedWrapper<T> Passed(T&& scoper) {
+ 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());
-}
-
-// Overload base::Passed() for std::unique_ptr<T>.
-template <typename T>
-static inline internal::PassedWrapper<std::unique_ptr<T>>
-Passed(std::unique_ptr<T>* scoper) {
- return internal::PassedWrapper<std::unique_ptr<T>>(std::move(*scoper));
-}
-
-template <typename T>
-static inline internal::PassedWrapper<std::unique_ptr<T>>
-Passed(std::unique_ptr<T> scoper) {
- return internal::PassedWrapper<std::unique_ptr<T>>(std::move(scoper));
-}
-
-// Overload base::Passed() for std::vector<std::unique_ptr<T>>.
-template <typename T, typename D, typename A>
-static inline internal::PassedWrapper<std::vector<std::unique_ptr<T, D>, A>>
-Passed(std::vector<std::unique_ptr<T, D>, A>* scoper) {
- return internal::PassedWrapper<std::vector<std::unique_ptr<T, D>, A>>(
- std::move(*scoper));
-}
-
-template <typename T, typename D, typename A>
-static inline internal::PassedWrapper<std::vector<std::unique_ptr<T, D>, A>>
-Passed(std::vector<std::unique_ptr<T, D>, A> scoper) {
- return internal::PassedWrapper<std::vector<std::unique_ptr<T, D>, A>>(
- std::move(scoper));
-}
-
-// Overload base::Passed() for std::map<K, std::unique_ptr<T>>.
-template <typename K, typename T, typename D, typename C, typename A>
-static inline internal::PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>>
-Passed(std::map<K, std::unique_ptr<T, D>, C, A>* scoper) {
- return internal::PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>>(
- std::move(*scoper));
-}
-
-template <typename K, typename T, typename D, typename C, typename A>
-static inline internal::PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>>
-Passed(std::map<K, std::unique_ptr<T, D>, C, A> scoper) {
- return internal::PassedWrapper<std::map<K, std::unique_ptr<T, D>, C, A>>(
- std::move(scoper));
+ return internal::PassedWrapper<T>(std::move(*scoper));
}
template <typename T>