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:
		
				
					committed by
					
						
						Mark Barolak
					
				
			
			
				
	
			
			
			
						parent
						
							0c400f67fc
						
					
				
				
					commit
					fbef0711cf
				
			@@ -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;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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 <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 <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)...);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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;
 | 
			
		||||
// 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>());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  template <typename F>
 | 
			
		||||
  operator ::testing::Action<F>() const {  // NOLINT(runtime/explicit)
 | 
			
		||||
    return ::testing::Action<F>(new typename Derived::template gmock_Impl<F>());
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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_;
 | 
			
		||||
};
 | 
			
		||||
// 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__))
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user