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

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: comment fix. rebase. Created 4 years, 6 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..4ed5909ff9f715a984563294ae69caf8a43e6623 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -46,6 +46,56 @@ 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 Lambda, typename Signature = decltype(&Lambda::operator())>
+struct ExtractLambdaRunTypeImpl;
+
+template <typename Lambda, typename R, typename... Args>
+struct ExtractLambdaRunTypeImpl<Lambda, R(Lambda::*)(Args...) const> {
+ using Type = R(Args...);
+};
+
+// Evaluated to RunType of the given C++11 lambda expression type.
+// Example:
+// ExtractLambdaRunType<[](int, char*) { return 0.1; }>
+// is evaluated to
+// double(int, char*);
+template <typename Lambda>
+using ExtractLambdaRunType = typename ExtractLambdaRunTypeImpl<Lambda>::Type;
+
+// IsCapturelessLambda<Functor> is a std::true_type if |Functor| is a
+// captureless lambda expression type.
dcheng 2016/07/01 13:29:47 Nit: it's a bit more accurate to say "callable typ
tzik 2016/07/01 14:34:57 OK, updated the names and comments. WDYT?
+// Example:
+// IsCapturelessLambda<void(*)()>::value is false.
+//
+// struct Foo {};
+// IsCapturelessLambda<void(Foo::*)()>::value is false.
+//
+// auto f = []() {};
+// IsCapturelessLambda<decltype(f)>::value is true.
+//
+// int i = 0;
+// auto g = [i]() {};
+// IsCapturelessLambda<decltype(g)>::value is false.
+template <typename Functor, typename SFINAE = void>
+struct IsCapturelessLambda : std::false_type {};
+
+template <typename Lambda>
+struct IsCapturelessLambda<Lambda, void_t<decltype(&Lambda::operator())>>
+ : std::is_convertible<Lambda, ExtractLambdaRunType<Lambda>*> {};
+
// 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 +126,30 @@ struct ForceVoidReturn<R(Args...)> {
// FunctorTraits<>
//
// See description at top of file.
-template <typename Functor>
+template <typename Functor, typename SFINAE = void>
struct FunctorTraits;
+// For captureless lambdas.
+template <typename Lambda>
+struct FunctorTraits<
+ Lambda, typename std::enable_if<IsCapturelessLambda<Lambda>::value>::type> {
+ using RunType = ExtractLambdaRunType<Lambda>;
+ static constexpr bool is_method = false;
+ static constexpr bool is_nullable = false;
+
+ template <typename... RunArgs>
+ static typename std::result_of<Lambda(RunArgs&&...)>::type
+ Invoke(const Lambda& lambda, RunArgs&&... args) {
+ return lambda(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 +164,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 +177,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 +192,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 +212,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 +246,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 +352,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 +374,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