diff options
author | Abseil Team <absl-team@google.com> | 2020-11-06 22:09:13 (GMT) |
---|---|---|
committer | Mark Barolak <mbar@google.com> | 2020-11-09 20:43:33 (GMT) |
commit | fbef0711cfce7b8f149aac773d30ae48ce3e166c (patch) | |
tree | 61ebc3eaf7f427a90b63e8b6814770ec0cfd8715 /googlemock | |
parent | 0c400f67fcf305869c5fb113dd296eca266c9725 (diff) | |
download | googletest-fbef0711cfce7b8f149aac773d30ae48ce3e166c.zip googletest-fbef0711cfce7b8f149aac773d30ae48ce3e166c.tar.gz googletest-fbef0711cfce7b8f149aac773d30ae48ce3e166c.tar.bz2 |
Googletest export
Change ACTION{,_Pn,_TEMPLATE} macros to build functors rather than ActionInterface<> subclasses, thus changing the Action<> wrappers they create to use the modernized (non-const) argument tuple type, allowing these macros to mutate their arguments.
Functor-based Action<>s deep-copy the implementing object, so have the functors use a shared_ptr to the non-trivial state of bound value parameters. No longer specialize that shared state to the particular action signature, encoding that information instead only in the instantiation of the implementation function.
PiperOrigin-RevId: 341116208
Diffstat (limited to 'googlemock')
-rw-r--r-- | googlemock/include/gmock/gmock-actions.h | 185 | ||||
-rw-r--r-- | googlemock/include/gmock/gmock-generated-actions.h | 122 | ||||
-rw-r--r-- | googlemock/include/gmock/gmock-generated-actions.h.pump | 122 |
3 files changed, 210 insertions, 219 deletions
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index f95be3f..fb33f7b 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -1480,68 +1480,72 @@ namespace internal { // TYPE DIRECTLY. struct ExcessiveArg {}; -// A helper class needed for implementing the ACTION* macros. -template <typename Result, class Impl> -class ActionHelper { - public: - template <typename... Ts> - static Result Perform(Impl* impl, const std::tuple<Ts...>& args) { - static constexpr size_t kMaxArgs = sizeof...(Ts) <= 10 ? sizeof...(Ts) : 10; - return Apply(impl, args, MakeIndexSequence<kMaxArgs>{}, - MakeIndexSequence<10 - kMaxArgs>{}); - } +// Builds an implementation of an Action<> for some particular signature, using +// a class defined by an ACTION* macro. +template <typename F, typename Impl> struct ActionImpl; - private: - template <typename... Ts, std::size_t... tuple_ids, std::size_t... rest_ids> - static Result Apply(Impl* impl, const std::tuple<Ts...>& args, - IndexSequence<tuple_ids...>, IndexSequence<rest_ids...>) { - return impl->template gmock_PerformImpl< - typename std::tuple_element<tuple_ids, std::tuple<Ts...>>::type...>( - args, std::get<tuple_ids>(args)..., - ((void)rest_ids, ExcessiveArg())...); - } +template <typename Impl> +struct ImplBase { + struct Holder { + // Allows each copy of the Action<> to get to the Impl. + explicit operator const Impl&() const { return *ptr; } + std::shared_ptr<Impl> ptr; + }; + using type = typename std::conditional<std::is_constructible<Impl>::value, + Impl, Holder>::type; }; -// A helper base class needed for implementing the ACTION* macros. -// Implements constructor and conversion operator for Action. -// -// Template specialization for parameterless Action. -template <typename Derived> -class ActionImpl { - public: - ActionImpl() = default; - - template <typename F> - operator ::testing::Action<F>() const { // NOLINT(runtime/explicit) - return ::testing::Action<F>(new typename Derived::template gmock_Impl<F>()); +template <typename R, typename... Args, typename Impl> +struct ActionImpl<R(Args...), Impl> : ImplBase<Impl>::type { + using Base = typename ImplBase<Impl>::type; + using function_type = R(Args...); + using args_type = std::tuple<Args...>; + + ActionImpl() = default; // Only defined if appropriate for Base. + explicit ActionImpl(std::shared_ptr<Impl> impl) : Base{std::move(impl)} { } + + R operator()(Args&&... arg) const { + static constexpr size_t kMaxArgs = + sizeof...(Args) <= 10 ? sizeof...(Args) : 10; + return Apply(MakeIndexSequence<kMaxArgs>{}, + MakeIndexSequence<10 - kMaxArgs>{}, + args_type{std::forward<Args>(arg)...}); } -}; - -// Template specialization for parameterized Action. -template <template <typename...> class Derived, typename... Ts> -class ActionImpl<Derived<Ts...>> { - public: - explicit ActionImpl(Ts... params) : params_(std::forward<Ts>(params)...) {} - template <typename F> - operator ::testing::Action<F>() const { // NOLINT(runtime/explicit) - return Apply<F>(MakeIndexSequence<sizeof...(Ts)>{}); + template <std::size_t... arg_id, std::size_t... excess_id> + R Apply(IndexSequence<arg_id...>, IndexSequence<excess_id...>, + const args_type& args) const { + // Impl need not be specific to the signature of action being implemented; + // only the implementing function body needs to have all of the specific + // types instantiated. Up to 10 of the args that are provided by the + // args_type get passed, followed by a dummy of unspecified type for the + // remainder up to 10 explicit args. + static const ExcessiveArg kExcessArg; + return static_cast<const Impl&>(*this).template gmock_PerformImpl< + /*function_type=*/function_type, /*return_type=*/R, + /*args_type=*/args_type, + /*argN_type=*/typename std::tuple_element<arg_id, args_type>::type...>( + /*args=*/args, std::get<arg_id>(args)..., + ((void)excess_id, kExcessArg)...); } +}; - private: - template <typename F, std::size_t... tuple_ids> - ::testing::Action<F> Apply(IndexSequence<tuple_ids...>) const { - return ::testing::Action<F>(new - typename Derived<Ts...>::template gmock_Impl<F>( - std::get<tuple_ids>(params_)...)); - } +// Stores a default-constructed Impl as part of the Action<>'s +// std::function<>. The Impl should be trivial to copy. +template <typename F, typename Impl> +::testing::Action<F> MakeAction() { + return ::testing::Action<F>(ActionImpl<F, Impl>()); +} - std::tuple<Ts...> params_; -}; +// Stores just the one given instance of Impl. +template <typename F, typename Impl> +::testing::Action<F> MakeAction(std::shared_ptr<Impl> impl) { + return ::testing::Action<F>(ActionImpl<F, Impl>(std::move(impl))); +} #define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \ , const arg##i##_type& arg##i GTEST_ATTRIBUTE_UNUSED_ -#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ const args_type& args GTEST_ATTRIBUTE_UNUSED_ GMOCK_PP_REPEAT( \ GMOCK_INTERNAL_ARG_UNUSED, , 10) @@ -1582,30 +1586,28 @@ class ActionImpl<Derived<Ts...>> { #define GMOCK_INTERNAL_ACTION(name, full_name, params) \ template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \ - class full_name : public ::testing::internal::ActionImpl< \ - full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>> { \ - using base_type = ::testing::internal::ActionImpl<full_name>; \ - \ + class full_name { \ public: \ - using base_type::base_type; \ + explicit full_name(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ + : impl_(std::make_shared<gmock_Impl>( \ + GMOCK_ACTION_GVALUE_PARAMS_(params))) { } \ + full_name(const full_name&) = default; \ + full_name(full_name&&) noexcept = default; \ template <typename F> \ - class gmock_Impl : public ::testing::ActionInterface<F> { \ + operator ::testing::Action<F>() const { \ + return ::testing::internal::MakeAction<F>(impl_); \ + } \ + private: \ + class gmock_Impl { \ public: \ - typedef F function_type; \ - typedef typename ::testing::internal::Function<F>::Result return_type; \ - typedef \ - typename ::testing::internal::Function<F>::ArgumentTuple args_type; \ explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ : GMOCK_ACTION_INIT_PARAMS_(params) {} \ - return_type Perform(const args_type& args) override { \ - return ::testing::internal::ActionHelper<return_type, \ - gmock_Impl>::Perform(this, \ - args); \ - } \ - template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + template <typename function_type, typename return_type, \ + typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ GMOCK_ACTION_FIELD_PARAMS_(params) \ }; \ + std::shared_ptr<const gmock_Impl> impl_; \ }; \ template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \ inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \ @@ -1614,48 +1616,37 @@ class ActionImpl<Derived<Ts...>> { GMOCK_ACTION_GVALUE_PARAMS_(params)); \ } \ template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \ - template <typename F> \ - template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ - typename ::testing::internal::Function<F>::Result \ - full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>::gmock_Impl< \ - F>::gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) \ - const + template <typename function_type, typename return_type, typename args_type, \ + GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + return_type full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>::gmock_Impl:: \ + gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const } // namespace internal +// Similar to GMOCK_INTERNAL_ACTION, but no bound parameters are stored. #define ACTION(name) \ - class name##Action : public ::testing::internal::ActionImpl<name##Action> { \ - using base_type = ::testing::internal::ActionImpl<name##Action>; \ - \ + class name##Action { \ public: \ - using base_type::base_type; \ - name##Action() = default; \ - /* Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134 */ \ - name##Action(const name##Action&) { } \ + explicit name##Action() noexcept {} \ + name##Action(const name##Action&) noexcept {} \ template <typename F> \ - class gmock_Impl : public ::testing::ActionInterface<F> { \ + operator ::testing::Action<F>() const { \ + return ::testing::internal::MakeAction<F, gmock_Impl>(); \ + } \ + private: \ + class gmock_Impl { \ public: \ - typedef F function_type; \ - typedef typename ::testing::internal::Function<F>::Result return_type; \ - typedef \ - typename ::testing::internal::Function<F>::ArgumentTuple args_type; \ - gmock_Impl() {} \ - return_type Perform(const args_type& args) override { \ - return ::testing::internal::ActionHelper<return_type, \ - gmock_Impl>::Perform(this, \ - args); \ - } \ - template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + template <typename function_type, typename return_type, \ + typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ }; \ }; \ inline name##Action name() GTEST_MUST_USE_RESULT_; \ inline name##Action name() { return name##Action(); } \ - template <typename F> \ - template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ - typename ::testing::internal::Function<F>::Result \ - name##Action::gmock_Impl<F>::gmock_PerformImpl( \ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + template <typename function_type, typename return_type, typename args_type, \ + GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + return_type name##Action::gmock_Impl::gmock_PerformImpl( \ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const #define ACTION_P(name, ...) \ GMOCK_INTERNAL_ACTION(name, name##ActionP, (__VA_ARGS__)) diff --git a/googlemock/include/gmock/gmock-generated-actions.h b/googlemock/include/gmock/gmock-generated-actions.h index 8446513..9240ce9 100644 --- a/googlemock/include/gmock/gmock-generated-actions.h +++ b/googlemock/include/gmock/gmock-generated-actions.h @@ -296,7 +296,7 @@ // Defines the copy constructor #define GMOCK_INTERNAL_DEFN_COPY_AND_0_VALUE_PARAMS() \ - {} // Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134 + noexcept {} // Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134 #define GMOCK_INTERNAL_DEFN_COPY_AND_1_VALUE_PARAMS(...) = default; #define GMOCK_INTERNAL_DEFN_COPY_AND_2_VALUE_PARAMS(...) = default; #define GMOCK_INTERNAL_DEFN_COPY_AND_3_VALUE_PARAMS(...) = default; @@ -429,66 +429,66 @@ #define GMOCK_ACTION_CLASS_(name, value_params)\ GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params) -#define ACTION_TEMPLATE(name, template_params, value_params)\ - template <GMOCK_INTERNAL_DECL_##template_params\ - GMOCK_INTERNAL_DECL_TYPE_##value_params>\ - class GMOCK_ACTION_CLASS_(name, value_params) {\ - public:\ - explicit GMOCK_ACTION_CLASS_(name, value_params)\ - GMOCK_INTERNAL_INIT_##value_params {}\ - GMOCK_ACTION_CLASS_(name, value_params)(\ - const GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params>&)\ - GMOCK_INTERNAL_DEFN_COPY_##value_params\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ - return_type Perform(const args_type& args) override {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ - return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const;\ - GMOCK_INTERNAL_DEFN_##value_params\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(\ - new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\ - }\ - GMOCK_INTERNAL_DEFN_##value_params\ - };\ - template <GMOCK_INTERNAL_DECL_##template_params\ - GMOCK_INTERNAL_DECL_TYPE_##value_params>\ - GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ - GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_;\ - template <GMOCK_INTERNAL_DECL_##template_params\ - GMOCK_INTERNAL_DECL_TYPE_##value_params>\ - inline GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ - GMOCK_INTERNAL_DECL_##value_params) {\ - return GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params>(\ - GMOCK_INTERNAL_LIST_##value_params);\ - }\ - template <GMOCK_INTERNAL_DECL_##template_params\ - GMOCK_INTERNAL_DECL_TYPE_##value_params>\ - template <typename F>\ - template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ - typename ::testing::internal::Function<F>::Result\ - GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\ - gmock_PerformImpl(\ +#define ACTION_TEMPLATE(name, template_params, value_params) \ + template <GMOCK_INTERNAL_DECL_##template_params \ + GMOCK_INTERNAL_DECL_TYPE_##value_params> \ + class GMOCK_ACTION_CLASS_(name, value_params) { \ + public: \ + explicit GMOCK_ACTION_CLASS_(name, value_params)( \ + GMOCK_INTERNAL_DECL_##value_params) \ + GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \ + = default; , \ + : impl_(std::make_shared<gmock_Impl>( \ + GMOCK_INTERNAL_LIST_##value_params)) { }) \ + GMOCK_ACTION_CLASS_(name, value_params)( \ + const GMOCK_ACTION_CLASS_(name, value_params)&) \ + GMOCK_INTERNAL_DEFN_COPY_##value_params \ + GMOCK_ACTION_CLASS_(name, value_params)( \ + GMOCK_ACTION_CLASS_(name, value_params)&&) \ + GMOCK_INTERNAL_DEFN_COPY_##value_params \ + template <typename F> \ + operator ::testing::Action<F>() const { \ + return GMOCK_PP_IF( \ + GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \ + (::testing::internal::MakeAction<F, gmock_Impl>()), \ + (::testing::internal::MakeAction<F>(impl_))); \ + } \ + private: \ + class gmock_Impl { \ + public: \ + explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {} \ + template <typename function_type, typename return_type, \ + typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ + GMOCK_INTERNAL_DEFN_##value_params \ + }; \ + GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \ + , std::shared_ptr<const gmock_Impl> impl_;) \ + }; \ + template <GMOCK_INTERNAL_DECL_##template_params \ + GMOCK_INTERNAL_DECL_TYPE_##value_params> \ + GMOCK_ACTION_CLASS_(name, value_params)< \ + GMOCK_INTERNAL_LIST_##template_params \ + GMOCK_INTERNAL_LIST_TYPE_##value_params> name( \ + GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_; \ + template <GMOCK_INTERNAL_DECL_##template_params \ + GMOCK_INTERNAL_DECL_TYPE_##value_params> \ + inline GMOCK_ACTION_CLASS_(name, value_params)< \ + GMOCK_INTERNAL_LIST_##template_params \ + GMOCK_INTERNAL_LIST_TYPE_##value_params> name( \ + GMOCK_INTERNAL_DECL_##value_params) { \ + return GMOCK_ACTION_CLASS_(name, value_params)< \ + GMOCK_INTERNAL_LIST_##template_params \ + GMOCK_INTERNAL_LIST_TYPE_##value_params>( \ + GMOCK_INTERNAL_LIST_##value_params); \ + } \ + template <GMOCK_INTERNAL_DECL_##template_params \ + GMOCK_INTERNAL_DECL_TYPE_##value_params> \ + template <typename function_type, typename return_type, typename args_type, \ + GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + return_type GMOCK_ACTION_CLASS_(name, value_params)< \ + GMOCK_INTERNAL_LIST_##template_params \ + GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl::gmock_PerformImpl( \ GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const namespace testing { diff --git a/googlemock/include/gmock/gmock-generated-actions.h.pump b/googlemock/include/gmock/gmock-generated-actions.h.pump index 0bdb42e..982caf9 100644 --- a/googlemock/include/gmock/gmock-generated-actions.h.pump +++ b/googlemock/include/gmock/gmock-generated-actions.h.pump @@ -181,7 +181,7 @@ $range j 0..i-1 $for i [[ #define GMOCK_INTERNAL_DEFN_COPY_AND_$i[[]]_VALUE_PARAMS$if i == 0[[() \ - {} // Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134 + noexcept {} // Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134 ]] $else [[(...) = default;]] @@ -243,66 +243,66 @@ $if i==1 [[P]] $elif i>=2 [[P$i]] $range k 0..n-1 -#define ACTION_TEMPLATE(name, template_params, value_params)\ - template <GMOCK_INTERNAL_DECL_##template_params\ - GMOCK_INTERNAL_DECL_TYPE_##value_params>\ - class GMOCK_ACTION_CLASS_(name, value_params) {\ - public:\ - explicit GMOCK_ACTION_CLASS_(name, value_params)\ - GMOCK_INTERNAL_INIT_##value_params {}\ - GMOCK_ACTION_CLASS_(name, value_params)(\ - const GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params>&)\ - GMOCK_INTERNAL_DEFN_COPY_##value_params\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ - return_type Perform(const args_type& args) override {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ - return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const;\ - GMOCK_INTERNAL_DEFN_##value_params\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(\ - new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\ - }\ - GMOCK_INTERNAL_DEFN_##value_params\ - };\ - template <GMOCK_INTERNAL_DECL_##template_params\ - GMOCK_INTERNAL_DECL_TYPE_##value_params>\ - GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ - GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_;\ - template <GMOCK_INTERNAL_DECL_##template_params\ - GMOCK_INTERNAL_DECL_TYPE_##value_params>\ - inline GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ - GMOCK_INTERNAL_DECL_##value_params) {\ - return GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params>(\ - GMOCK_INTERNAL_LIST_##value_params);\ - }\ - template <GMOCK_INTERNAL_DECL_##template_params\ - GMOCK_INTERNAL_DECL_TYPE_##value_params>\ - template <typename F>\ - template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ - typename ::testing::internal::Function<F>::Result\ - GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\ - gmock_PerformImpl(\ +#define ACTION_TEMPLATE(name, template_params, value_params) \ + template <GMOCK_INTERNAL_DECL_##template_params \ + GMOCK_INTERNAL_DECL_TYPE_##value_params> \ + class GMOCK_ACTION_CLASS_(name, value_params) { \ + public: \ + explicit GMOCK_ACTION_CLASS_(name, value_params)( \ + GMOCK_INTERNAL_DECL_##value_params) \ + GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \ + = default; , \ + : impl_(std::make_shared<gmock_Impl>( \ + GMOCK_INTERNAL_LIST_##value_params)) { }) \ + GMOCK_ACTION_CLASS_(name, value_params)( \ + const GMOCK_ACTION_CLASS_(name, value_params)&) \ + GMOCK_INTERNAL_DEFN_COPY_##value_params \ + GMOCK_ACTION_CLASS_(name, value_params)( \ + GMOCK_ACTION_CLASS_(name, value_params)&&) \ + GMOCK_INTERNAL_DEFN_COPY_##value_params \ + template <typename F> \ + operator ::testing::Action<F>() const { \ + return GMOCK_PP_IF( \ + GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \ + (::testing::internal::MakeAction<F, gmock_Impl>()), \ + (::testing::internal::MakeAction<F>(impl_))); \ + } \ + private: \ + class gmock_Impl { \ + public: \ + explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {} \ + template <typename function_type, typename return_type, \ + typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ + GMOCK_INTERNAL_DEFN_##value_params \ + }; \ + GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \ + , std::shared_ptr<const gmock_Impl> impl_;) \ + }; \ + template <GMOCK_INTERNAL_DECL_##template_params \ + GMOCK_INTERNAL_DECL_TYPE_##value_params> \ + GMOCK_ACTION_CLASS_(name, value_params)< \ + GMOCK_INTERNAL_LIST_##template_params \ + GMOCK_INTERNAL_LIST_TYPE_##value_params> name( \ + GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_; \ + template <GMOCK_INTERNAL_DECL_##template_params \ + GMOCK_INTERNAL_DECL_TYPE_##value_params> \ + inline GMOCK_ACTION_CLASS_(name, value_params)< \ + GMOCK_INTERNAL_LIST_##template_params \ + GMOCK_INTERNAL_LIST_TYPE_##value_params> name( \ + GMOCK_INTERNAL_DECL_##value_params) { \ + return GMOCK_ACTION_CLASS_(name, value_params)< \ + GMOCK_INTERNAL_LIST_##template_params \ + GMOCK_INTERNAL_LIST_TYPE_##value_params>( \ + GMOCK_INTERNAL_LIST_##value_params); \ + } \ + template <GMOCK_INTERNAL_DECL_##template_params \ + GMOCK_INTERNAL_DECL_TYPE_##value_params> \ + template <typename function_type, typename return_type, typename args_type, \ + GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + return_type GMOCK_ACTION_CLASS_(name, value_params)< \ + GMOCK_INTERNAL_LIST_##template_params \ + GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl::gmock_PerformImpl( \ GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const namespace testing { |