Googletest export
Replace pump'd code for DoAll with variadic templates. PiperOrigin-RevId: 225584656
This commit is contained in:
		
				
					committed by
					
						
						Mark Barolak
					
				
			
			
				
	
			
			
			
						parent
						
							b5f5c596a9
						
					
				
				
					commit
					096fb37a19
				
			@@ -574,7 +574,7 @@ class ReturnAction {
 | 
			
		||||
  // This template type conversion operator allows Return(x) to be
 | 
			
		||||
  // used in ANY function that returns x's type.
 | 
			
		||||
  template <typename F>
 | 
			
		||||
  operator Action<F>() const {
 | 
			
		||||
  operator Action<F>() const {  // NOLINT
 | 
			
		||||
    // Assert statement belongs here because this is the best place to verify
 | 
			
		||||
    // conditions on F. It produces the clearest error messages
 | 
			
		||||
    // in most compilers.
 | 
			
		||||
@@ -587,6 +587,8 @@ class ReturnAction {
 | 
			
		||||
    GTEST_COMPILE_ASSERT_(
 | 
			
		||||
        !is_reference<Result>::value,
 | 
			
		||||
        use_ReturnRef_instead_of_Return_to_return_a_reference);
 | 
			
		||||
    static_assert(!std::is_void<Result>::value,
 | 
			
		||||
                  "Can't use Return() on an action expected to return `void`.");
 | 
			
		||||
    return Action<F>(new Impl<R, F>(value_));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -1017,51 +1019,6 @@ void PrintTo(const ReferenceWrapper<T>& ref, ::std::ostream* os) {
 | 
			
		||||
  UniversalPrinter<T&>::Print(value, os);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Does two actions sequentially.  Used for implementing the DoAll(a1,
 | 
			
		||||
// a2, ...) action.
 | 
			
		||||
template <typename Action1, typename Action2>
 | 
			
		||||
class DoBothAction {
 | 
			
		||||
 public:
 | 
			
		||||
  DoBothAction(Action1 action1, Action2 action2)
 | 
			
		||||
      : action1_(action1), action2_(action2) {}
 | 
			
		||||
 | 
			
		||||
  // This template type conversion operator allows DoAll(a1, ..., a_n)
 | 
			
		||||
  // to be used in ANY function of compatible type.
 | 
			
		||||
  template <typename F>
 | 
			
		||||
  operator Action<F>() const {
 | 
			
		||||
    return Action<F>(new Impl<F>(action1_, action2_));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // Implements the DoAll(...) action for a particular function type F.
 | 
			
		||||
  template <typename F>
 | 
			
		||||
  class Impl : public ActionInterface<F> {
 | 
			
		||||
   public:
 | 
			
		||||
    typedef typename Function<F>::Result Result;
 | 
			
		||||
    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
 | 
			
		||||
    typedef typename Function<F>::MakeResultVoid VoidResult;
 | 
			
		||||
 | 
			
		||||
    Impl(const Action<VoidResult>& action1, const Action<F>& action2)
 | 
			
		||||
        : action1_(action1), action2_(action2) {}
 | 
			
		||||
 | 
			
		||||
    Result Perform(const ArgumentTuple& args) override {
 | 
			
		||||
      action1_.Perform(args);
 | 
			
		||||
      return action2_.Perform(args);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   private:
 | 
			
		||||
    const Action<VoidResult> action1_;
 | 
			
		||||
    const Action<F> action2_;
 | 
			
		||||
 | 
			
		||||
    GTEST_DISALLOW_ASSIGN_(Impl);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Action1 action1_;
 | 
			
		||||
  Action2 action2_;
 | 
			
		||||
 | 
			
		||||
  GTEST_DISALLOW_ASSIGN_(DoBothAction);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename InnerAction, size_t... I>
 | 
			
		||||
struct WithArgsAction {
 | 
			
		||||
  InnerAction action;
 | 
			
		||||
@@ -1080,6 +1037,35 @@ struct WithArgsAction {
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename... Actions>
 | 
			
		||||
struct DoAllAction {
 | 
			
		||||
 private:
 | 
			
		||||
  template <typename... Args, size_t... I>
 | 
			
		||||
  std::vector<Action<void(Args...)>> Convert(IndexSequence<I...>) const {
 | 
			
		||||
    return {std::get<I>(actions)...};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  std::tuple<Actions...> actions;
 | 
			
		||||
 | 
			
		||||
  template <typename R, typename... Args>
 | 
			
		||||
  operator Action<R(Args...)>() const {  // NOLINT
 | 
			
		||||
    struct Op {
 | 
			
		||||
      std::vector<Action<void(Args...)>> converted;
 | 
			
		||||
      Action<R(Args...)> last;
 | 
			
		||||
      R operator()(Args... args) const {
 | 
			
		||||
        auto tuple_args = std::forward_as_tuple(std::forward<Args>(args)...);
 | 
			
		||||
        for (auto& a : converted) {
 | 
			
		||||
          a.Perform(tuple_args);
 | 
			
		||||
        }
 | 
			
		||||
        return last.Perform(tuple_args);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
    return Op{Convert<Args...>(MakeIndexSequence<sizeof...(Actions) - 1>()),
 | 
			
		||||
              std::get<sizeof...(Actions) - 1>(actions)};
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
 | 
			
		||||
// An Unused object can be implicitly constructed from ANY value.
 | 
			
		||||
@@ -1130,6 +1116,14 @@ Action<To>::Action(const Action<From>& from)
 | 
			
		||||
                : new internal::ActionAdaptor<To, From>(from)) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates an action that does actions a1, a2, ..., sequentially in
 | 
			
		||||
// each invocation.
 | 
			
		||||
template <typename... Action>
 | 
			
		||||
internal::DoAllAction<typename std::decay<Action>::type...> DoAll(
 | 
			
		||||
    Action&&... action) {
 | 
			
		||||
  return {std::forward_as_tuple(std::forward<Action>(action)...)};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithArg<k>(an_action) creates an action that passes the k-th
 | 
			
		||||
// (0-based) argument of the mock function to an_action and performs
 | 
			
		||||
// it.  It adapts an action accepting one argument to one that accepts
 | 
			
		||||
 
 | 
			
		||||
@@ -474,97 +474,6 @@ class ActionHelper {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
 | 
			
		||||
// Creates an action that does actions a1, a2, ..., sequentially in
 | 
			
		||||
// each invocation.
 | 
			
		||||
template <typename Action1, typename Action2>
 | 
			
		||||
inline internal::DoBothAction<Action1, Action2>
 | 
			
		||||
DoAll(Action1 a1, Action2 a2) {
 | 
			
		||||
  return internal::DoBothAction<Action1, Action2>(a1, a2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Action1, typename Action2, typename Action3>
 | 
			
		||||
inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
 | 
			
		||||
    Action3> >
 | 
			
		||||
DoAll(Action1 a1, Action2 a2, Action3 a3) {
 | 
			
		||||
  return DoAll(a1, DoAll(a2, a3));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Action1, typename Action2, typename Action3,
 | 
			
		||||
    typename Action4>
 | 
			
		||||
inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
 | 
			
		||||
    internal::DoBothAction<Action3, Action4> > >
 | 
			
		||||
DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4) {
 | 
			
		||||
  return DoAll(a1, DoAll(a2, a3, a4));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Action1, typename Action2, typename Action3,
 | 
			
		||||
    typename Action4, typename Action5>
 | 
			
		||||
inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
 | 
			
		||||
    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
 | 
			
		||||
    Action5> > > >
 | 
			
		||||
DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5) {
 | 
			
		||||
  return DoAll(a1, DoAll(a2, a3, a4, a5));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Action1, typename Action2, typename Action3,
 | 
			
		||||
    typename Action4, typename Action5, typename Action6>
 | 
			
		||||
inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
 | 
			
		||||
    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
 | 
			
		||||
    internal::DoBothAction<Action5, Action6> > > > >
 | 
			
		||||
DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6) {
 | 
			
		||||
  return DoAll(a1, DoAll(a2, a3, a4, a5, a6));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Action1, typename Action2, typename Action3,
 | 
			
		||||
    typename Action4, typename Action5, typename Action6, typename Action7>
 | 
			
		||||
inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
 | 
			
		||||
    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
 | 
			
		||||
    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
 | 
			
		||||
    Action7> > > > > >
 | 
			
		||||
DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
 | 
			
		||||
    Action7 a7) {
 | 
			
		||||
  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Action1, typename Action2, typename Action3,
 | 
			
		||||
    typename Action4, typename Action5, typename Action6, typename Action7,
 | 
			
		||||
    typename Action8>
 | 
			
		||||
inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
 | 
			
		||||
    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
 | 
			
		||||
    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
 | 
			
		||||
    internal::DoBothAction<Action7, Action8> > > > > > >
 | 
			
		||||
DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
 | 
			
		||||
    Action7 a7, Action8 a8) {
 | 
			
		||||
  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Action1, typename Action2, typename Action3,
 | 
			
		||||
    typename Action4, typename Action5, typename Action6, typename Action7,
 | 
			
		||||
    typename Action8, typename Action9>
 | 
			
		||||
inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
 | 
			
		||||
    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
 | 
			
		||||
    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
 | 
			
		||||
    internal::DoBothAction<Action7, internal::DoBothAction<Action8,
 | 
			
		||||
    Action9> > > > > > > >
 | 
			
		||||
DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
 | 
			
		||||
    Action7 a7, Action8 a8, Action9 a9) {
 | 
			
		||||
  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Action1, typename Action2, typename Action3,
 | 
			
		||||
    typename Action4, typename Action5, typename Action6, typename Action7,
 | 
			
		||||
    typename Action8, typename Action9, typename Action10>
 | 
			
		||||
inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
 | 
			
		||||
    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
 | 
			
		||||
    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
 | 
			
		||||
    internal::DoBothAction<Action7, internal::DoBothAction<Action8,
 | 
			
		||||
    internal::DoBothAction<Action9, Action10> > > > > > > > >
 | 
			
		||||
DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
 | 
			
		||||
    Action7 a7, Action8 a8, Action9 a9, Action10 a10) {
 | 
			
		||||
  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9, a10));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
// The ACTION* family of macros can be used in a namespace scope to
 | 
			
		||||
 
 | 
			
		||||
@@ -165,34 +165,6 @@ $template
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
 | 
			
		||||
// Creates an action that does actions a1, a2, ..., sequentially in
 | 
			
		||||
// each invocation.
 | 
			
		||||
$range i 2..n
 | 
			
		||||
$for i [[
 | 
			
		||||
$range j 2..i
 | 
			
		||||
$var types = [[$for j, [[typename Action$j]]]]
 | 
			
		||||
$var Aas = [[$for j [[, Action$j a$j]]]]
 | 
			
		||||
 | 
			
		||||
template <typename Action1, $types>
 | 
			
		||||
$range k 1..i-1
 | 
			
		||||
 | 
			
		||||
inline $for k [[internal::DoBothAction<Action$k, ]]Action$i$for k  [[>]]
 | 
			
		||||
 | 
			
		||||
DoAll(Action1 a1$Aas) {
 | 
			
		||||
$if i==2 [[
 | 
			
		||||
 | 
			
		||||
  return internal::DoBothAction<Action1, Action2>(a1, a2);
 | 
			
		||||
]] $else [[
 | 
			
		||||
$range j2 2..i
 | 
			
		||||
 | 
			
		||||
  return DoAll(a1, DoAll($for j2, [[a$j2]]));
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
// The ACTION* family of macros can be used in a namespace scope to
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user