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
This commit is contained in:
Abseil Team 2020-11-06 17:09:13 -05:00 committed by Mark Barolak
parent 0c400f67fc
commit fbef0711cf
3 changed files with 212 additions and 221 deletions

View File

@ -1480,68 +1480,72 @@ namespace internal {
// TYPE DIRECTLY. // TYPE DIRECTLY.
struct ExcessiveArg {}; struct ExcessiveArg {};
// A helper class needed for implementing the ACTION* macros. // Builds an implementation of an Action<> for some particular signature, using
template <typename Result, class Impl> // a class defined by an ACTION* macro.
class ActionHelper { template <typename F, typename Impl> struct ActionImpl;
public:
template <typename... Ts> template <typename Impl>
static Result Perform(Impl* impl, const std::tuple<Ts...>& args) { struct ImplBase {
static constexpr size_t kMaxArgs = sizeof...(Ts) <= 10 ? sizeof...(Ts) : 10; struct Holder {
return Apply(impl, args, MakeIndexSequence<kMaxArgs>{}, // Allows each copy of the Action<> to get to the Impl.
MakeIndexSequence<10 - kMaxArgs>{}); 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;
};
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)...});
} }
private: template <std::size_t... arg_id, std::size_t... excess_id>
template <typename... Ts, std::size_t... tuple_ids, std::size_t... rest_ids> R Apply(IndexSequence<arg_id...>, IndexSequence<excess_id...>,
static Result Apply(Impl* impl, const std::tuple<Ts...>& args, const args_type& args) const {
IndexSequence<tuple_ids...>, IndexSequence<rest_ids...>) { // Impl need not be specific to the signature of action being implemented;
return impl->template gmock_PerformImpl< // only the implementing function body needs to have all of the specific
typename std::tuple_element<tuple_ids, std::tuple<Ts...>>::type...>( // types instantiated. Up to 10 of the args that are provided by the
args, std::get<tuple_ids>(args)..., // args_type get passed, followed by a dummy of unspecified type for the
((void)rest_ids, ExcessiveArg())...); // 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)...);
} }
}; };
// A helper base class needed for implementing the ACTION* macros. // Stores a default-constructed Impl as part of the Action<>'s
// Implements constructor and conversion operator for Action. // std::function<>. The Impl should be trivial to copy.
// template <typename F, typename Impl>
// Template specialization for parameterless Action. ::testing::Action<F> MakeAction() {
template <typename Derived> return ::testing::Action<F>(ActionImpl<F, Impl>());
class ActionImpl { }
public:
ActionImpl() = default;
template <typename F> // Stores just the one given instance of Impl.
operator ::testing::Action<F>() const { // NOLINT(runtime/explicit) template <typename F, typename Impl>
return ::testing::Action<F>(new typename Derived::template gmock_Impl<F>()); ::testing::Action<F> MakeAction(std::shared_ptr<Impl> impl) {
} return ::testing::Action<F>(ActionImpl<F, Impl>(std::move(impl)));
}; }
// 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)>{});
}
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_)...));
}
std::tuple<Ts...> params_;
};
#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \ #define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \
, const arg##i##_type& arg##i GTEST_ATTRIBUTE_UNUSED_ , 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( \ const args_type& args GTEST_ATTRIBUTE_UNUSED_ GMOCK_PP_REPEAT( \
GMOCK_INTERNAL_ARG_UNUSED, , 10) GMOCK_INTERNAL_ARG_UNUSED, , 10)
@ -1582,30 +1586,28 @@ class ActionImpl<Derived<Ts...>> {
#define GMOCK_INTERNAL_ACTION(name, full_name, params) \ #define GMOCK_INTERNAL_ACTION(name, full_name, params) \
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \ template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
class full_name : public ::testing::internal::ActionImpl< \ class full_name { \
full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>> { \
using base_type = ::testing::internal::ActionImpl<full_name>; \
\
public: \ 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> \ 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: \ 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)) \ explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \
: GMOCK_ACTION_INIT_PARAMS_(params) {} \ : GMOCK_ACTION_INIT_PARAMS_(params) {} \
return_type Perform(const args_type& args) override { \ template <typename function_type, typename return_type, \
return ::testing::internal::ActionHelper<return_type, \ typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
gmock_Impl>::Perform(this, \
args); \
} \
template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
GMOCK_ACTION_FIELD_PARAMS_(params) \ GMOCK_ACTION_FIELD_PARAMS_(params) \
}; \ }; \
std::shared_ptr<const gmock_Impl> impl_; \
}; \ }; \
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \ template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \ inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
@ -1614,48 +1616,37 @@ class ActionImpl<Derived<Ts...>> {
GMOCK_ACTION_GVALUE_PARAMS_(params)); \ GMOCK_ACTION_GVALUE_PARAMS_(params)); \
} \ } \
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \ template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
template <typename F> \ template <typename function_type, typename return_type, typename args_type, \
template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
typename ::testing::internal::Function<F>::Result \ return_type full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>::gmock_Impl:: \
full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>::gmock_Impl< \ gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
F>::gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) \
const
} // namespace internal } // namespace internal
// Similar to GMOCK_INTERNAL_ACTION, but no bound parameters are stored.
#define ACTION(name) \ #define ACTION(name) \
class name##Action : public ::testing::internal::ActionImpl<name##Action> { \ class name##Action { \
using base_type = ::testing::internal::ActionImpl<name##Action>; \
\
public: \ public: \
using base_type::base_type; \ explicit name##Action() noexcept {} \
name##Action() = default; \ name##Action(const name##Action&) noexcept {} \
/* Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134 */ \
name##Action(const name##Action&) { } \
template <typename F> \ 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: \ public: \
typedef F function_type; \ template <typename function_type, typename return_type, \
typedef typename ::testing::internal::Function<F>::Result return_type; \ typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
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_> \
return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
}; \ }; \
}; \ }; \
inline name##Action name() GTEST_MUST_USE_RESULT_; \ inline name##Action name() GTEST_MUST_USE_RESULT_; \
inline name##Action name() { return name##Action(); } \ inline name##Action name() { return name##Action(); } \
template <typename F> \ template <typename function_type, typename return_type, typename args_type, \
template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
typename ::testing::internal::Function<F>::Result \ return_type name##Action::gmock_Impl::gmock_PerformImpl( \
name##Action::gmock_Impl<F>::gmock_PerformImpl( \ GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
#define ACTION_P(name, ...) \ #define ACTION_P(name, ...) \
GMOCK_INTERNAL_ACTION(name, name##ActionP, (__VA_ARGS__)) GMOCK_INTERNAL_ACTION(name, name##ActionP, (__VA_ARGS__))

View File

@ -296,7 +296,7 @@
// Defines the copy constructor // Defines the copy constructor
#define GMOCK_INTERNAL_DEFN_COPY_AND_0_VALUE_PARAMS() \ #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_1_VALUE_PARAMS(...) = default;
#define GMOCK_INTERNAL_DEFN_COPY_AND_2_VALUE_PARAMS(...) = default; #define GMOCK_INTERNAL_DEFN_COPY_AND_2_VALUE_PARAMS(...) = default;
#define GMOCK_INTERNAL_DEFN_COPY_AND_3_VALUE_PARAMS(...) = default; #define GMOCK_INTERNAL_DEFN_COPY_AND_3_VALUE_PARAMS(...) = default;
@ -429,66 +429,66 @@
#define GMOCK_ACTION_CLASS_(name, value_params)\ #define GMOCK_ACTION_CLASS_(name, value_params)\
GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params) GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
#define ACTION_TEMPLATE(name, template_params, value_params)\ #define ACTION_TEMPLATE(name, template_params, value_params) \
template <GMOCK_INTERNAL_DECL_##template_params\ template <GMOCK_INTERNAL_DECL_##template_params \
GMOCK_INTERNAL_DECL_TYPE_##value_params>\ GMOCK_INTERNAL_DECL_TYPE_##value_params> \
class GMOCK_ACTION_CLASS_(name, value_params) {\ class GMOCK_ACTION_CLASS_(name, value_params) { \
public:\ public: \
explicit GMOCK_ACTION_CLASS_(name, value_params)\ explicit GMOCK_ACTION_CLASS_(name, value_params)( \
GMOCK_INTERNAL_INIT_##value_params {}\ GMOCK_INTERNAL_DECL_##value_params) \
GMOCK_ACTION_CLASS_(name, value_params)(\ GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
const GMOCK_ACTION_CLASS_(name, value_params)<\ = default; , \
GMOCK_INTERNAL_LIST_##template_params\ : impl_(std::make_shared<gmock_Impl>( \
GMOCK_INTERNAL_LIST_TYPE_##value_params>&)\ GMOCK_INTERNAL_LIST_##value_params)) { }) \
GMOCK_INTERNAL_DEFN_COPY_##value_params\ GMOCK_ACTION_CLASS_(name, value_params)( \
template <typename F>\ const GMOCK_ACTION_CLASS_(name, value_params)&) \
class gmock_Impl : public ::testing::ActionInterface<F> {\ GMOCK_INTERNAL_DEFN_COPY_##value_params \
public:\ GMOCK_ACTION_CLASS_(name, value_params)( \
typedef F function_type;\ GMOCK_ACTION_CLASS_(name, value_params)&&) \
typedef typename ::testing::internal::Function<F>::Result return_type;\ GMOCK_INTERNAL_DEFN_COPY_##value_params \
typedef typename ::testing::internal::Function<F>::ArgumentTuple\ template <typename F> \
args_type;\ operator ::testing::Action<F>() const { \
explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ return GMOCK_PP_IF( \
return_type Perform(const args_type& args) override {\ GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ (::testing::internal::MakeAction<F, gmock_Impl>()), \
Perform(this, args);\ (::testing::internal::MakeAction<F>(impl_))); \
}\ } \
template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ private: \
return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const;\ class gmock_Impl { \
GMOCK_INTERNAL_DEFN_##value_params\ public: \
};\ explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {} \
template <typename F> operator ::testing::Action<F>() const {\ template <typename function_type, typename return_type, \
return ::testing::Action<F>(\ typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\ return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
}\ GMOCK_INTERNAL_DEFN_##value_params \
GMOCK_INTERNAL_DEFN_##value_params\ }; \
};\ GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
template <GMOCK_INTERNAL_DECL_##template_params\ , std::shared_ptr<const gmock_Impl> impl_;) \
GMOCK_INTERNAL_DECL_TYPE_##value_params>\ }; \
GMOCK_ACTION_CLASS_(name, value_params)<\ template <GMOCK_INTERNAL_DECL_##template_params \
GMOCK_INTERNAL_LIST_##template_params\ GMOCK_INTERNAL_DECL_TYPE_##value_params> \
GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ GMOCK_ACTION_CLASS_(name, value_params)< \
GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_;\ GMOCK_INTERNAL_LIST_##template_params \
template <GMOCK_INTERNAL_DECL_##template_params\ GMOCK_INTERNAL_LIST_TYPE_##value_params> name( \
GMOCK_INTERNAL_DECL_TYPE_##value_params>\ GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_; \
inline GMOCK_ACTION_CLASS_(name, value_params)<\ template <GMOCK_INTERNAL_DECL_##template_params \
GMOCK_INTERNAL_LIST_##template_params\ GMOCK_INTERNAL_DECL_TYPE_##value_params> \
GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ inline GMOCK_ACTION_CLASS_(name, value_params)< \
GMOCK_INTERNAL_DECL_##value_params) {\ GMOCK_INTERNAL_LIST_##template_params \
return GMOCK_ACTION_CLASS_(name, value_params)<\ GMOCK_INTERNAL_LIST_TYPE_##value_params> name( \
GMOCK_INTERNAL_LIST_##template_params\ GMOCK_INTERNAL_DECL_##value_params) { \
GMOCK_INTERNAL_LIST_TYPE_##value_params>(\ return GMOCK_ACTION_CLASS_(name, value_params)< \
GMOCK_INTERNAL_LIST_##value_params);\ GMOCK_INTERNAL_LIST_##template_params \
}\ GMOCK_INTERNAL_LIST_TYPE_##value_params>( \
template <GMOCK_INTERNAL_DECL_##template_params\ GMOCK_INTERNAL_LIST_##value_params); \
GMOCK_INTERNAL_DECL_TYPE_##value_params>\ } \
template <typename F>\ template <GMOCK_INTERNAL_DECL_##template_params \
template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ GMOCK_INTERNAL_DECL_TYPE_##value_params> \
typename ::testing::internal::Function<F>::Result\ template <typename function_type, typename return_type, typename args_type, \
GMOCK_ACTION_CLASS_(name, value_params)<\ GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
GMOCK_INTERNAL_LIST_##template_params\ return_type GMOCK_ACTION_CLASS_(name, value_params)< \
GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\ GMOCK_INTERNAL_LIST_##template_params \
gmock_PerformImpl(\ GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl::gmock_PerformImpl( \
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
namespace testing { namespace testing {

View File

@ -181,7 +181,7 @@ $range j 0..i-1
$for i [[ $for i [[
#define GMOCK_INTERNAL_DEFN_COPY_AND_$i[[]]_VALUE_PARAMS$if i == 0[[() \ #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;]] ]] $else [[(...) = default;]]
@ -243,66 +243,66 @@ $if i==1 [[P]] $elif i>=2 [[P$i]]
$range k 0..n-1 $range k 0..n-1
#define ACTION_TEMPLATE(name, template_params, value_params)\ #define ACTION_TEMPLATE(name, template_params, value_params) \
template <GMOCK_INTERNAL_DECL_##template_params\ template <GMOCK_INTERNAL_DECL_##template_params \
GMOCK_INTERNAL_DECL_TYPE_##value_params>\ GMOCK_INTERNAL_DECL_TYPE_##value_params> \
class GMOCK_ACTION_CLASS_(name, value_params) {\ class GMOCK_ACTION_CLASS_(name, value_params) { \
public:\ public: \
explicit GMOCK_ACTION_CLASS_(name, value_params)\ explicit GMOCK_ACTION_CLASS_(name, value_params)( \
GMOCK_INTERNAL_INIT_##value_params {}\ GMOCK_INTERNAL_DECL_##value_params) \
GMOCK_ACTION_CLASS_(name, value_params)(\ GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
const GMOCK_ACTION_CLASS_(name, value_params)<\ = default; , \
GMOCK_INTERNAL_LIST_##template_params\ : impl_(std::make_shared<gmock_Impl>( \
GMOCK_INTERNAL_LIST_TYPE_##value_params>&)\ GMOCK_INTERNAL_LIST_##value_params)) { }) \
GMOCK_INTERNAL_DEFN_COPY_##value_params\ GMOCK_ACTION_CLASS_(name, value_params)( \
template <typename F>\ const GMOCK_ACTION_CLASS_(name, value_params)&) \
class gmock_Impl : public ::testing::ActionInterface<F> {\ GMOCK_INTERNAL_DEFN_COPY_##value_params \
public:\ GMOCK_ACTION_CLASS_(name, value_params)( \
typedef F function_type;\ GMOCK_ACTION_CLASS_(name, value_params)&&) \
typedef typename ::testing::internal::Function<F>::Result return_type;\ GMOCK_INTERNAL_DEFN_COPY_##value_params \
typedef typename ::testing::internal::Function<F>::ArgumentTuple\ template <typename F> \
args_type;\ operator ::testing::Action<F>() const { \
explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ return GMOCK_PP_IF( \
return_type Perform(const args_type& args) override {\ GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ (::testing::internal::MakeAction<F, gmock_Impl>()), \
Perform(this, args);\ (::testing::internal::MakeAction<F>(impl_))); \
}\ } \
template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ private: \
return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const;\ class gmock_Impl { \
GMOCK_INTERNAL_DEFN_##value_params\ public: \
};\ explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {} \
template <typename F> operator ::testing::Action<F>() const {\ template <typename function_type, typename return_type, \
return ::testing::Action<F>(\ typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\ return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
}\ GMOCK_INTERNAL_DEFN_##value_params \
GMOCK_INTERNAL_DEFN_##value_params\ }; \
};\ GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
template <GMOCK_INTERNAL_DECL_##template_params\ , std::shared_ptr<const gmock_Impl> impl_;) \
GMOCK_INTERNAL_DECL_TYPE_##value_params>\ }; \
GMOCK_ACTION_CLASS_(name, value_params)<\ template <GMOCK_INTERNAL_DECL_##template_params \
GMOCK_INTERNAL_LIST_##template_params\ GMOCK_INTERNAL_DECL_TYPE_##value_params> \
GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ GMOCK_ACTION_CLASS_(name, value_params)< \
GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_;\ GMOCK_INTERNAL_LIST_##template_params \
template <GMOCK_INTERNAL_DECL_##template_params\ GMOCK_INTERNAL_LIST_TYPE_##value_params> name( \
GMOCK_INTERNAL_DECL_TYPE_##value_params>\ GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_; \
inline GMOCK_ACTION_CLASS_(name, value_params)<\ template <GMOCK_INTERNAL_DECL_##template_params \
GMOCK_INTERNAL_LIST_##template_params\ GMOCK_INTERNAL_DECL_TYPE_##value_params> \
GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ inline GMOCK_ACTION_CLASS_(name, value_params)< \
GMOCK_INTERNAL_DECL_##value_params) {\ GMOCK_INTERNAL_LIST_##template_params \
return GMOCK_ACTION_CLASS_(name, value_params)<\ GMOCK_INTERNAL_LIST_TYPE_##value_params> name( \
GMOCK_INTERNAL_LIST_##template_params\ GMOCK_INTERNAL_DECL_##value_params) { \
GMOCK_INTERNAL_LIST_TYPE_##value_params>(\ return GMOCK_ACTION_CLASS_(name, value_params)< \
GMOCK_INTERNAL_LIST_##value_params);\ GMOCK_INTERNAL_LIST_##template_params \
}\ GMOCK_INTERNAL_LIST_TYPE_##value_params>( \
template <GMOCK_INTERNAL_DECL_##template_params\ GMOCK_INTERNAL_LIST_##value_params); \
GMOCK_INTERNAL_DECL_TYPE_##value_params>\ } \
template <typename F>\ template <GMOCK_INTERNAL_DECL_##template_params \
template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ GMOCK_INTERNAL_DECL_TYPE_##value_params> \
typename ::testing::internal::Function<F>::Result\ template <typename function_type, typename return_type, typename args_type, \
GMOCK_ACTION_CLASS_(name, value_params)<\ GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
GMOCK_INTERNAL_LIST_##template_params\ return_type GMOCK_ACTION_CLASS_(name, value_params)< \
GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\ GMOCK_INTERNAL_LIST_##template_params \
gmock_PerformImpl(\ GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl::gmock_PerformImpl( \
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
namespace testing { namespace testing {