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.
//
// Usage:
// void LogError(char* error_message) {
// bool LogError(char* error_message) {
// if (error_message) {
// 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));
// cb.Run(42, nullptr);
// CHECK_EQ(true, cb.Run(42, nullptr));
//
// Note in the example above that the type(s) passed to `IgnoreArgs`
// represent the additional prepended parameters (those which will be
// "ignored").
template <typename... Preargs, typename... Args>
RepeatingCallback<void(Preargs..., Args...)> IgnoreArgs(
RepeatingCallback<void(Args...)> callback) {
template <typename... Preargs, typename... Args, typename R>
RepeatingCallback<R(Preargs..., Args...)> IgnoreArgs(
RepeatingCallback<R(Args...)> callback) {
return callback ? ::base::BindRepeating(
[](RepeatingCallback<void(Args...)> callback,
Preargs..., Args... args) {
std::move(callback).Run(std::forward<Args>(args)...);
[](RepeatingCallback<R(Args...)> callback, Preargs...,
Args... args) {
return std::move(callback).Run(
std::forward<Args>(args)...);
},
std::move(callback))
: RepeatingCallback<void(Preargs..., Args...)>();
: RepeatingCallback<R(Preargs..., Args...)>();
}
// As above, but for OnceCallback.
template <typename... Preargs, typename... Args>
OnceCallback<void(Preargs..., Args...)> IgnoreArgs(
OnceCallback<void(Args...)> callback) {
template <typename... Preargs, typename... Args, typename R>
OnceCallback<R(Preargs..., Args...)> IgnoreArgs(
OnceCallback<R(Args...)> callback) {
return callback ? ::base::BindOnce(
[](OnceCallback<void(Args...)> callback, Preargs...,
[](OnceCallback<R(Args...)> callback, Preargs...,
Args... args) {
std::move(callback).Run(std::forward<Args>(args)...);
return std::move(callback).Run(
std::forward<Args>(args)...);
},
std::move(callback))
: OnceCallback<void(Preargs..., Args...)>();
: OnceCallback<R(Preargs..., Args...)>();
}
// ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures

@ -137,6 +137,10 @@ void IncrementWithRef(int& value) {
value++;
}
int IncrementAndReturn(int* value) {
return ++(*value);
}
TEST(CallbackHelpersTest, ScopedClosureRunnerHasClosure) {
base::ScopedClosureRunner runner1;
EXPECT_FALSE(runner1);
@ -362,6 +366,41 @@ TEST(CallbackHelpersTest, IgnoreArgs_EmptyCallback) {
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) {
int count = 0;
auto tie_cb =

@ -716,13 +716,16 @@ designated callback type expects. The extra arguments can be ignored as long
as they are leading.
```cpp
void LogError(char* error_message) {
if (error_message)
bool LogError(char* error_message) {
if (error_message) {
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));
cb.Run(42, nullptr);
CHECK_EQ(true, cb.Run(42, nullptr));
```
Note in the example above that the type(s) passed to `IgnoreArgs` represent