Commit d58a8923 authored by tzik's avatar tzik Committed by Commit Bot

Support C++17 noexcept function type in base::Bind

In C++17, noexcept keyword is a part of the function type, and that
causes a pattern match failure on base::Bind implementation.
This CL fixes the failure by falling it back to bare function cases.

Bug: 752720
Change-Id: I98c71977fa3fd759956c86e394fb9e30179c951c
Reviewed-on: https://chromium-review.googlesource.com/1027530Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Taiju Tsuiki <tzik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553913}
parent 899655fb
......@@ -397,9 +397,9 @@ struct FunctorTraits<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) {
return function(std::forward<RunArgs>(args)...);
template <typename Function, typename... RunArgs>
static R Invoke(Function&& function, RunArgs&&... args) {
return std::forward<Function>(function)(std::forward<RunArgs>(args)...);
}
};
......@@ -440,8 +440,8 @@ struct FunctorTraits<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...),
template <typename Method, typename ReceiverPtr, typename... RunArgs>
static R Invoke(Method method,
ReceiverPtr&& receiver_ptr,
RunArgs&&... args) {
return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
......@@ -455,14 +455,31 @@ struct FunctorTraits<R (Receiver::*)(Args...) const> {
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,
template <typename Method, typename ReceiverPtr, typename... RunArgs>
static R Invoke(Method method,
ReceiverPtr&& receiver_ptr,
RunArgs&&... args) {
return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
}
};
#ifdef __cpp_noexcept_function_type
// noexcept makes a distinct function type in C++17.
// I.e. `void(*)()` and `void(*)() noexcept` are same in pre-C++17, and
// different in C++17.
template <typename R, typename... Args>
struct FunctorTraits<R (*)(Args...) noexcept> : FunctorTraits<R (*)(Args...)> {
};
template <typename R, typename Receiver, typename... Args>
struct FunctorTraits<R (Receiver::*)(Args...) noexcept>
: FunctorTraits<R (Receiver::*)(Args...)> {};
template <typename R, typename Receiver, typename... Args>
struct FunctorTraits<R (Receiver::*)(Args...) const noexcept>
: FunctorTraits<R (Receiver::*)(Args...) const> {};
#endif
// For IgnoreResults.
template <typename T>
struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
......
......@@ -311,6 +311,10 @@ void TakesACallback(const Closure& callback) {
callback.Run();
}
int Noexcept() noexcept {
return 42;
}
class BindTest : public ::testing::Test {
public:
BindTest() {
......@@ -326,6 +330,8 @@ class BindTest : public ::testing::Test {
}
static int IntFunc0() { return static_func_mock_ptr->IntMethod0(); }
int NoexceptMethod() noexcept { return 42; }
int ConstNoexceptMethod() const noexcept { return 42; }
protected:
StrictMock<NoRef> no_ref_;
......@@ -1469,6 +1475,16 @@ TEST_F(BindTest, UnwrapPassed) {
EXPECT_EQ(p, internal::Unwrap(Passed(WrapUnique(p))).get());
}
TEST_F(BindTest, BindNoexcept) {
EXPECT_EQ(42, base::BindOnce(&Noexcept).Run());
EXPECT_EQ(
42,
base::BindOnce(&BindTest::NoexceptMethod, base::Unretained(this)).Run());
EXPECT_EQ(
42, base::BindOnce(&BindTest::ConstNoexceptMethod, base::Unretained(this))
.Run());
}
// Test null callbacks cause a DCHECK.
TEST(BindDeathTest, NullCallback) {
base::Callback<void(int)> null_cb;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment