summaryrefslogtreecommitdiff
path: root/googlemock/include
diff options
context:
space:
mode:
authorAaron Jacobs <jacobsa@google.com>2022-04-26 14:39:03 -0700
committerCopybara-Service <copybara-worker@google.com>2022-04-26 14:39:37 -0700
commitc144d78f8295da3dbae3ad2d5fe66a9a42f8ce74 (patch)
treea7db04a970e8d04908f72c4b4af1613a0f10b156 /googlemock/include
parente33c2b24ca3e13df961ed369f7ed21e4cfcf9eec (diff)
downloadgoogletest-git-c144d78f8295da3dbae3ad2d5fe66a9a42f8ce74.tar.gz
Support move-only and &&-qualified actions in WithArgs.
PiperOrigin-RevId: 444671005 Change-Id: I7df5f038caf17afb60d4fb35434ff0b656d4c954
Diffstat (limited to 'googlemock/include')
-rw-r--r--googlemock/include/gmock/gmock-actions.h57
1 files changed, 50 insertions, 7 deletions
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h
index ecc72d53..5836f179 100644
--- a/googlemock/include/gmock/gmock-actions.h
+++ b/googlemock/include/gmock/gmock-actions.h
@@ -1279,17 +1279,60 @@ class IgnoreResultAction {
template <typename InnerAction, size_t... I>
struct WithArgsAction {
- InnerAction action;
+ InnerAction inner_action;
- // The inner action could be anything convertible to Action<X>.
- // We use the conversion operator to detect the signature of the inner Action.
+ // The signature of the function as seen by the inner action, given an out
+ // action with the given result and argument types.
template <typename R, typename... Args>
+ using InnerSignature =
+ R(typename std::tuple_element<I, std::tuple<Args...>>::type...);
+
+ // Rather than a call operator, we must define conversion operators to
+ // particular action types. This is necessary for embedded actions like
+ // DoDefault(), which rely on an action conversion operators rather than
+ // providing a call operator because even with a particular set of arguments
+ // they don't have a fixed return type.
+
+ template <typename R, typename... Args,
+ typename std::enable_if<
+ std::is_convertible<
+ InnerAction,
+ // Unfortunately we can't use the InnerSignature alias here;
+ // MSVC complains about the I parameter pack not being
+ // expanded (error C3520) despite it being expanded in the
+ // type alias.
+ OnceAction<R(typename std::tuple_element<
+ I, std::tuple<Args...>>::type...)>>::value,
+ int>::type = 0>
+ operator OnceAction<R(Args...)>() && { // NOLINT
+ struct OA {
+ OnceAction<InnerSignature<R, Args...>> inner_action;
+
+ R operator()(Args&&... args) && {
+ return std::move(inner_action)
+ .Call(std::get<I>(
+ std::forward_as_tuple(std::forward<Args>(args)...))...);
+ }
+ };
+
+ return OA{std::move(inner_action)};
+ }
+
+ template <typename R, typename... Args,
+ typename std::enable_if<
+ std::is_convertible<
+ const InnerAction&,
+ // Unfortunately we can't use the InnerSignature alias here;
+ // MSVC complains about the I parameter pack not being
+ // expanded (error C3520) despite it being expanded in the
+ // type alias.
+ Action<R(typename std::tuple_element<
+ I, std::tuple<Args...>>::type...)>>::value,
+ int>::type = 0>
operator Action<R(Args...)>() const { // NOLINT
- using TupleType = std::tuple<Args...>;
- Action<R(typename std::tuple_element<I, TupleType>::type...)> converted(
- action);
+ Action<InnerSignature<R, Args...>> converted(inner_action);
- return [converted](Args... args) -> R {
+ return [converted](Args&&... args) -> R {
return converted.Perform(std::forward_as_tuple(
std::get<I>(std::forward_as_tuple(std::forward<Args>(args)...))...));
};