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 {