Allow implicitly converting a lambda to mojo::Callback using C++11
This uses C++11 type traits to check if a type is convertible to an
std::function and if so uses an appropriate adaptor for mojo::Callback.
This replaces the fairly hacky operator() detection that was in place.
R=viettrungluu@chromium.org
Review URL: https://codereview.chromium.org/1402523002 .
diff --git a/mojo/public/cpp/bindings/callback.h b/mojo/public/cpp/bindings/callback.h
index 0a06e76..24a2f43 100644
--- a/mojo/public/cpp/bindings/callback.h
+++ b/mojo/public/cpp/bindings/callback.h
@@ -5,6 +5,7 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
#define MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
+#include <functional>
#include <type_traits>
#include "mojo/public/cpp/bindings/lib/callback_internal.h"
@@ -38,13 +39,13 @@
// ownership of |runnable|.
explicit Callback(Runnable* runnable) : sink_(runnable) {}
- // As above, but can take an object that isn't derived from Runnable, so long
- // as it has a compatible operator() or Run() method. operator() will be
- // preferred if the type has both.
+ // Adapts any type that is copy-constructable and has a compatible Run method
+ // or is convertible to std::function<void(Args...)> (such as a lambda of the
+ // correct type).
template <typename Sink>
Callback(const Sink& sink) {
using sink_type = typename std::conditional<
- internal::HasCompatibleCallOperator<Sink, Args...>::value,
+ std::is_convertible<Sink, std::function<void(Args...)>>::value,
FunctorAdapter<Sink>, RunnableAdapter<Sink>>::type;
sink_ = internal::SharedPtr<Runnable>(new sink_type(sink));
}
diff --git a/mojo/public/cpp/bindings/lib/callback_internal.h b/mojo/public/cpp/bindings/lib/callback_internal.h
index 9df5b40..ec52b34 100644
--- a/mojo/public/cpp/bindings/lib/callback_internal.h
+++ b/mojo/public/cpp/bindings/lib/callback_internal.h
@@ -22,31 +22,6 @@
typedef const String& ForwardType;
};
-template <typename T, typename... Args>
-struct HasCompatibleCallOperator {
- // This template's second parameter is the signature of the operator()
- // overload we want to try to detect:
- // void operator()(Args...) const;
- template <typename U,
- void (U::*)(
- typename internal::Callback_ParamTraits<Args>::ForwardType...)
- const>
- struct TestType {};
-
- // This matches type U if it has a call operator with the
- // expected signature.
- template <typename U>
- static YesType Test(TestType<U, &U::operator()>*);
-
- // This matches anything else.
- template <typename U>
- static NoType Test(...);
-
- // HasCompatibleCallOperator<T, Args...>::value will be true if T has a
- // compatible call operator.
- enum { value = (sizeof(Test<T>(nullptr)) == sizeof(YesType)) };
-};
-
} // namespace internal
} // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/callback_unittest.cc b/mojo/public/cpp/bindings/tests/callback_unittest.cc
index 158b21e..a423090 100644
--- a/mojo/public/cpp/bindings/tests/callback_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/callback_unittest.cc
@@ -62,37 +62,6 @@
(*g_calls)++;
}
-static_assert(!internal::HasCompatibleCallOperator<RunnableNoArgs>::value,
- "HasCompatibleCallOperator<Runnable>");
-static_assert(!internal::HasCompatibleCallOperator<RunnableOneArg, int>::value,
- "HasCompatibleCallOperator<RunnableOneArg, int>");
-static_assert(!internal::HasCompatibleCallOperator<RunnableStringArgByConstRef,
- String>::value,
- "HasCompatibleCallOperator<RunnableStringArgByConstRef, String>");
-static_assert(!internal::HasCompatibleCallOperator<RunnableMoveOnlyParam,
- ExampleMoveOnlyType>::value,
- "HasCompatibleCallOperator<RunnableMoveOnlyParam, String>");
-
-auto lambda_one = []() {};
-static_assert(internal::HasCompatibleCallOperator<decltype(lambda_one)>::value,
- "HasCompatibleCallOperator<lambda []() {}>");
-
-auto lambda_two = [](int x) {};
-static_assert(
- internal::HasCompatibleCallOperator<decltype(lambda_two), int>::value,
- "HasCompatibleCallOperator<lambda [](int x) {}, int>");
-
-auto lambda_three = [](const String& s) {};
-static_assert(
- internal::HasCompatibleCallOperator<decltype(lambda_three), String>::value,
- "HasCompatibleCallOperator<lambda [](const String& s) {}, String>");
-
-auto lambda_four = [](ExampleMoveOnlyType m) {};
-static_assert(internal::HasCompatibleCallOperator<decltype(lambda_four),
- ExampleMoveOnlyType>::value,
- "HasCompatibleCallOperator<lambda [](ExampleMoveOnlyType) {}, "
- "ExampleMoveOnlyType>");
-
// Tests constructing and invoking a mojo::Callback from objects with a
// compatible Run() method (called 'runnables'), from lambdas, and from function
// pointers.