0

Allow base::IgnoreArgs to return a non-void type

Bug: None
Change-Id: Idac3691c9635d31ee54b91bb3193a16f091751be
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5756150
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Reviewed-by: Peter Kasting <pkasting@chromium.org>
Commit-Queue: Keren Zhu <kerenzhu@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1336833}
This commit is contained in:
Keren Zhu
2024-08-03 00:00:12 +00:00
committed by Chromium LUCI CQ
parent b2be7dd5be
commit 9cd105c806
3 changed files with 66 additions and 20 deletions

@ -122,41 +122,45 @@ SplitOnceCallback(OnceCallback<void(Args...)> callback) {
// additional parameters. Returns a null callback if `callback` is null. // additional parameters. Returns a null callback if `callback` is null.
// //
// Usage: // Usage:
// void LogError(char* error_message) { // bool LogError(char* error_message) {
// if (error_message) { // if (error_message) {
// cout << "Log: " << error_message << endl; // cout << "Log: " << error_message << endl;
// return false;
// } // }
// return true;
// } // }
// base::RepeatingCallback<void(int, char*)> cb = // base::RepeatingCallback<bool(int, char*)> cb =
// base::IgnoreArgs<int>(base::BindRepeating(&LogError)); // base::IgnoreArgs<int>(base::BindRepeating(&LogError));
// cb.Run(42, nullptr); // CHECK_EQ(true, cb.Run(42, nullptr));
// //
// Note in the example above that the type(s) passed to `IgnoreArgs` // Note in the example above that the type(s) passed to `IgnoreArgs`
// represent the additional prepended parameters (those which will be // represent the additional prepended parameters (those which will be
// "ignored"). // "ignored").
template <typename... Preargs, typename... Args> template <typename... Preargs, typename... Args, typename R>
RepeatingCallback<void(Preargs..., Args...)> IgnoreArgs( RepeatingCallback<R(Preargs..., Args...)> IgnoreArgs(
RepeatingCallback<void(Args...)> callback) { RepeatingCallback<R(Args...)> callback) {
return callback ? ::base::BindRepeating( return callback ? ::base::BindRepeating(
[](RepeatingCallback<void(Args...)> callback, [](RepeatingCallback<R(Args...)> callback, Preargs...,
Preargs..., Args... args) { Args... args) {
std::move(callback).Run(std::forward<Args>(args)...); return std::move(callback).Run(
std::forward<Args>(args)...);
}, },
std::move(callback)) std::move(callback))
: RepeatingCallback<void(Preargs..., Args...)>(); : RepeatingCallback<R(Preargs..., Args...)>();
} }
// As above, but for OnceCallback. // As above, but for OnceCallback.
template <typename... Preargs, typename... Args> template <typename... Preargs, typename... Args, typename R>
OnceCallback<void(Preargs..., Args...)> IgnoreArgs( OnceCallback<R(Preargs..., Args...)> IgnoreArgs(
OnceCallback<void(Args...)> callback) { OnceCallback<R(Args...)> callback) {
return callback ? ::base::BindOnce( return callback ? ::base::BindOnce(
[](OnceCallback<void(Args...)> callback, Preargs..., [](OnceCallback<R(Args...)> callback, Preargs...,
Args... args) { Args... args) {
std::move(callback).Run(std::forward<Args>(args)...); return std::move(callback).Run(
std::forward<Args>(args)...);
}, },
std::move(callback)) std::move(callback))
: OnceCallback<void(Preargs..., Args...)>(); : OnceCallback<R(Preargs..., Args...)>();
} }
// ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures // ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures

@ -137,6 +137,10 @@ void IncrementWithRef(int& value) {
value++; value++;
} }
int IncrementAndReturn(int* value) {
return ++(*value);
}
TEST(CallbackHelpersTest, ScopedClosureRunnerHasClosure) { TEST(CallbackHelpersTest, ScopedClosureRunnerHasClosure) {
base::ScopedClosureRunner runner1; base::ScopedClosureRunner runner1;
EXPECT_FALSE(runner1); EXPECT_FALSE(runner1);
@ -362,6 +366,41 @@ TEST(CallbackHelpersTest, IgnoreArgs_EmptyCallback) {
EXPECT_FALSE(once_int_cb); EXPECT_FALSE(once_int_cb);
} }
TEST(CallbackHelpersTest, IgnoreArgs_NonVoidReturn) {
int count = 0;
base::RepeatingCallback<int(void)> repeating_no_param_cb =
base::BindRepeating(&IncrementAndReturn, &count);
base::OnceCallback<int(void)> once_no_param_cb =
base::BindOnce(&IncrementAndReturn, &count);
base::RepeatingCallback<int(int)> repeating_int_cb =
base::IgnoreArgs<int>(repeating_no_param_cb);
EXPECT_EQ(0, count);
EXPECT_EQ(1, repeating_int_cb.Run(42));
EXPECT_EQ(1, count);
EXPECT_EQ(2, repeating_int_cb.Run(42));
EXPECT_EQ(2, count);
base::OnceCallback<int(int)> once_int_cb =
base::IgnoreArgs<int>(std::move(once_no_param_cb));
EXPECT_EQ(2, count);
EXPECT_EQ(3, std::move(once_int_cb).Run(42));
EXPECT_EQ(3, count);
// Ignore only some (one) argument and forward the rest.
auto repeating_cb = base::BindRepeating(&IncrementAndReturn);
auto repeating_cb_with_extra_arg = base::IgnoreArgs<bool>(repeating_cb);
EXPECT_EQ(4, repeating_cb_with_extra_arg.Run(false, &count));
EXPECT_EQ(4, count);
// Ignore two arguments and forward the rest.
auto once_cb = base::BindOnce(&IncrementAndReturn);
auto once_cb_with_extra_arg =
base::IgnoreArgs<char, bool>(std::move(once_cb));
EXPECT_EQ(5, std::move(once_cb_with_extra_arg).Run('d', false, &count));
EXPECT_EQ(5, count);
}
TEST(CallbackHelpersTest, ForwardRepeatingCallbacks) { TEST(CallbackHelpersTest, ForwardRepeatingCallbacks) {
int count = 0; int count = 0;
auto tie_cb = auto tie_cb =

@ -716,13 +716,16 @@ designated callback type expects. The extra arguments can be ignored as long
as they are leading. as they are leading.
```cpp ```cpp
void LogError(char* error_message) { bool LogError(char* error_message) {
if (error_message) if (error_message) {
cout << "Log: " << error_message << endl; cout << "Log: " << error_message << endl;
return false;
}
return true;
} }
base::RepeatingCallback<void(int, char*)> cb = base::RepeatingCallback<bool(int, char*)> cb =
base::IgnoreArgs<int>(base::BindRepeating(&LogError)); base::IgnoreArgs<int>(base::BindRepeating(&LogError));
cb.Run(42, nullptr); CHECK_EQ(true, cb.Run(42, nullptr));
``` ```
Note in the example above that the type(s) passed to `IgnoreArgs` represent Note in the example above that the type(s) passed to `IgnoreArgs` represent