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:

committed by
Chromium LUCI CQ

parent
b2be7dd5be
commit
9cd105c806
@ -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
|
||||
|
Reference in New Issue
Block a user