diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index b0a6bdef..46e42626 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -940,7 +940,7 @@ class [[nodiscard]] ReturnAction final { std::is_convertible, // std::is_move_constructible>::value>::type> operator OnceAction() && { // NOLINT - return Impl(std::move(value_)); + return OnceImpl(std::move(value_)); } template class Impl final { public: - // The constructor used when the return value is allowed to move from the - // input value (i.e. we are converting to OnceAction). - explicit Impl(R&& input_value) - : state_(new State(std::move(input_value))) {} - - // The constructor used when the return value is not allowed to move from - // the input value (i.e. we are converting to Action). explicit Impl(const R& input_value) : state_(new State(input_value)) {} U operator()() && { return std::move(state_->value); } @@ -996,18 +989,6 @@ class [[nodiscard]] ReturnAction final { // explicit constructor from R. value(ImplicitCast_(internal::as_const(input_value))) {} - // As above, but for the case where we're moving from the ReturnAction - // object because it's being used as a OnceAction. - explicit State(R&& input_value_in) - : input_value(std::move(input_value_in)), - // For the same reason as above we make an implicit conversion to U - // before initializing the value. - // - // Unlike above we provide the input value as an rvalue to the - // implicit conversion because this is a OnceAction: it's fine if it - // wants to consume the input value. - value(ImplicitCast_(std::move(input_value))) {} - // A copy of the value originally provided by the user. We retain this in // addition to the value of the mock function's result type below in case // the latter is a reference-like type. See the std::string_view example @@ -1085,6 +1066,23 @@ class [[nodiscard]] ReturnAction final { const std::shared_ptr state_; }; + // Implements the Return(x) action for a mock function that returns type U, + // but is only executed at most once. This allows us to store the original + // value and move construct the return value type on the first (and only) + // call. + template + class OnceImpl final { + public: + explicit OnceImpl(R&& input_value) + : input_value_(new R(std::move(input_value))) {} + + U operator()() && { return std::move(*input_value_); } + + private: + // Move the input value to the heap and make it copyable. + const std::shared_ptr input_value_; + }; + R value_; };