From e90fe2485641bab0d6af4500192dc503384950d1 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Wed, 9 Apr 2025 17:56:54 -0700 Subject: [PATCH] `gmock-actions`: add a missing conversion operator to `WithArgsAction`. PiperOrigin-RevId: 745802500 Change-Id: I8cf7b69f89af8615e9c405b1e6552d3e12ebf93d --- googlemock/include/gmock/gmock-actions.h | 24 ++++++++++++++++++++++++ googlemock/test/gmock-actions_test.cc | 16 ++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index ef870936..5fe50e3d 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -1455,6 +1455,30 @@ struct WithArgsAction { return OA{std::move(inner_action)}; } + // As above, but in the case where we want to create a OnceAction from a const + // WithArgsAction. This is fine as long as the inner action doesn't need to + // move any of its state to create a OnceAction. + template < + typename R, typename... Args, + typename std::enable_if< + std::is_convertible>...)>>::value, + int>::type = 0> + operator OnceAction() const& { // NOLINT + struct OA { + OnceAction> inner_action; + + R operator()(Args&&... args) && { + return std::move(inner_action) + .Call(std::get( + std::forward_as_tuple(std::forward(args)...))...); + } + }; + + return OA{inner_action}; + } + template < typename R, typename... Args, typename std::enable_if< diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index 84db5115..46b0e918 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -1645,6 +1645,22 @@ TEST(WithArgsTest, RefQualifiedInnerAction) { EXPECT_EQ(19, mock.AsStdFunction()(0, 17)); } +// It should be fine to provide an lvalue WithArgsAction to WillOnce, even when +// the inner action only wants to convert to OnceAction. +TEST(WithArgsTest, ProvideAsLvalueToWillOnce) { + struct SomeAction { + operator OnceAction() const { // NOLINT + return [](const int arg) { return arg + 2; }; + } + }; + + const auto wa = WithArg<1>(SomeAction{}); + + MockFunction mock; + EXPECT_CALL(mock, Call).WillOnce(wa); + EXPECT_EQ(19, mock.AsStdFunction()(0, 17)); +} + #ifndef GTEST_OS_WINDOWS_MOBILE class SetErrnoAndReturnTest : public testing::Test {