Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3661)

Unified Diff: base/bind_internal.h

Issue 2115533002: Allow binding captureless lambdas into base::Callback by base::Bind (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@05_remove_runnable
Patch Set: rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/bind_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/bind_internal.h
diff --git a/base/bind_internal.h b/base/bind_internal.h
index 6b692a85a9d5424231489d964226d38f5b5932da..41c34ffea3c704f3054ade3aca889bdbd470082c 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -46,6 +46,60 @@ namespace internal {
// BindState<> -- Stores the curried parameters, and is the main entry point
// into the Bind() system.
+template <typename...>
+struct make_void {
+ using type = void;
+};
+
+// A clone of C++17 std::void_t.
+// Unlike the original version, we need |make_void| as a helper struct to avoid
+// a C++14 defect.
+// ref: http://en.cppreference.com/w/cpp/types/void_t
+// ref: http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558
+template <typename... Ts>
+using void_t = typename make_void<Ts...>::type;
+
+template <typename Callable,
+ typename Signature = decltype(&Callable::operator())>
+struct ExtractCallableRunTypeImpl;
+
+template <typename Callable, typename R, typename... Args>
+struct ExtractCallableRunTypeImpl<Callable, R(Callable::*)(Args...) const> {
+ using Type = R(Args...);
+};
+
+// Evaluated to RunType of the given callable type.
+// Example:
+// auto f = [](int, char*) { return 0.1; };
+// ExtractCallableRunType<decltype(f)>
+// is evaluated to
+// double(int, char*);
+template <typename Callable>
+using ExtractCallableRunType =
+ typename ExtractCallableRunTypeImpl<Callable>::Type;
+
+// IsConvertibleToRunType<Functor> is std::true_type if |Functor| has operator()
+// and convertible to the corresponding function pointer. Otherwise, it's
+// std::false_type.
+// Example:
+// IsConvertibleToRunType<void(*)()>::value is false.
+//
+// struct Foo {};
+// IsConvertibleToRunType<void(Foo::*)()>::value is false.
+//
+// auto f = []() {};
+// IsConvertibleToRunType<decltype(f)>::value is true.
+//
+// int i = 0;
+// auto g = [i]() {};
+// IsConvertibleToRunType<decltype(g)>::value is false.
+template <typename Functor, typename SFINAE = void>
+struct IsConvertibleToRunType : std::false_type {};
+
+template <typename Callable>
+struct IsConvertibleToRunType<Callable, void_t<decltype(&Callable::operator())>>
+ : std::is_convertible<Callable, ExtractCallableRunType<Callable>*> {};
+
// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
// pointer to a RefCounted type.
// Implementation note: This non-specialized case handles zero-arity case only.
@@ -76,14 +130,34 @@ struct ForceVoidReturn<R(Args...)> {
// FunctorTraits<>
//
// See description at top of file.
-template <typename Functor>
+template <typename Functor, typename SFINAE = void>
struct FunctorTraits;
+// For a callable type that is convertible to the corresponding function type.
+// This specialization is intended to allow binding captureless lambdas by
+// base::Bind(), based on the fact that captureless lambdas can be convertible
+// to the function type while capturing lambdas can't.
+template <typename Functor>
+struct FunctorTraits<
+ Functor,
+ typename std::enable_if<IsConvertibleToRunType<Functor>::value>::type> {
+ using RunType = ExtractCallableRunType<Functor>;
+ static constexpr bool is_method = false;
+ static constexpr bool is_nullable = false;
+
+ template <typename... RunArgs>
+ static ExtractReturnType<RunType>
+ Invoke(const Functor& functor, RunArgs&&... args) {
+ return functor(std::forward<RunArgs>(args)...);
+ }
+};
+
// For functions.
template <typename R, typename... Args>
struct FunctorTraits<R (*)(Args...)> {
using RunType = R(Args...);
static constexpr bool is_method = false;
+ static constexpr bool is_nullable = true;
template <typename... RunArgs>
static R Invoke(R (*function)(Args...), RunArgs&&... args) {
@@ -98,6 +172,7 @@ template <typename R, typename... Args>
struct FunctorTraits<R(__stdcall*)(Args...)> {
using RunType = R(Args...);
static constexpr bool is_method = false;
+ static constexpr bool is_nullable = true;
template <typename... RunArgs>
static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
@@ -110,6 +185,7 @@ template <typename R, typename... Args>
struct FunctorTraits<R(__fastcall*)(Args...)> {
using RunType = R(Args...);
static constexpr bool is_method = false;
+ static constexpr bool is_nullable = true;
template <typename... RunArgs>
static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
@@ -124,6 +200,7 @@ template <typename R, typename Receiver, typename... Args>
struct FunctorTraits<R (Receiver::*)(Args...)> {
using RunType = R(Receiver*, Args...);
static constexpr bool is_method = true;
+ static constexpr bool is_nullable = true;
template <typename ReceiverPtr, typename... RunArgs>
static R Invoke(R (Receiver::*method)(Args...),
@@ -143,6 +220,7 @@ template <typename R, typename Receiver, typename... Args>
struct FunctorTraits<R (Receiver::*)(Args...) const> {
using RunType = R(const Receiver*, Args...);
static constexpr bool is_method = true;
+ static constexpr bool is_nullable = true;
template <typename ReceiverPtr, typename... RunArgs>
static R Invoke(R (Receiver::*method)(Args...) const,
@@ -176,6 +254,7 @@ template <typename R, typename... Args, CopyMode copy_mode>
struct FunctorTraits<Callback<R(Args...), copy_mode>> {
using RunType = R(Args...);
static constexpr bool is_method = false;
+ static constexpr bool is_nullable = true;
template <typename CallbackType, typename... RunArgs>
static R Invoke(CallbackType&& callback, RunArgs&&... args) {
@@ -281,6 +360,17 @@ struct MakeUnboundRunTypeImpl {
using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>;
using Type = MakeFunctionType<ReturnType, UnboundArgs>;
};
+template <typename Functor>
+typename std::enable_if<FunctorTraits<Functor>::is_nullable, bool>::type
+IsNull(const Functor& functor) {
+ return !functor;
+}
+
+template <typename Functor>
+typename std::enable_if<!FunctorTraits<Functor>::is_nullable, bool>::type
+IsNull(const Functor&) {
+ return false;
+}
// BindState<>
//
@@ -292,7 +382,7 @@ struct BindState final : BindStateBase {
: BindStateBase(&Destroy),
functor_(std::move(functor)),
bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
- DCHECK(functor_);
+ DCHECK(!IsNull(functor_));
}
Functor functor_;
« no previous file with comments | « no previous file | base/bind_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698