diff options
author | Aaron Jacobs <jacobsa@google.com> | 2022-04-26 14:39:03 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-04-26 14:39:37 -0700 |
commit | c144d78f8295da3dbae3ad2d5fe66a9a42f8ce74 (patch) | |
tree | a7db04a970e8d04908f72c4b4af1613a0f10b156 /googlemock/include | |
parent | e33c2b24ca3e13df961ed369f7ed21e4cfcf9eec (diff) | |
download | googletest-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.h | 57 |
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)...))...)); }; |