Googletest export

Replace pump'd code for DoAll with variadic templates.

PiperOrigin-RevId: 225584656
This commit is contained in:
Abseil Team 2018-12-14 15:24:21 -05:00 committed by Mark Barolak
parent b5f5c596a9
commit 096fb37a19
3 changed files with 40 additions and 165 deletions

View File

@ -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

View File

@ -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

View File

@ -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