Skip to content

Commit

Permalink
Googletest export
Browse files Browse the repository at this point in the history
Rewrite InvokeArgument action without using pump.

PiperOrigin-RevId: 340861582
  • Loading branch information
ofats authored and suertreus committed Nov 5, 2020
1 parent fb98f74 commit 710f9c1
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 103 deletions.
9 changes: 0 additions & 9 deletions googlemock/include/gmock/gmock-actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -1539,15 +1539,6 @@ class ActionImpl<Derived<Ts...>> {
std::tuple<Ts...> params_;
};

// internal::InvokeArgument - a helper for InvokeArgument action.
// The basic overloads are provided here for generic functors.
// Overloads for other custom-callables are provided in the
// internal/custom/gmock-generated-actions.h header.
template <typename F, typename... Args>
auto InvokeArgument(F f, Args... args) -> decltype(f(args...)) {
return f(args...);
}

#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_ \
Expand Down
114 changes: 38 additions & 76 deletions googlemock/include/gmock/gmock-generated-actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,10 +491,8 @@
gmock_PerformImpl(\
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const


namespace testing {


// The ACTION*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
Expand All @@ -505,24 +503,52 @@ namespace testing {
# pragma warning(disable:4100)
#endif

// Various overloads for InvokeArgument<N>().
//
namespace internal {

// internal::InvokeArgument - a helper for InvokeArgument action.
// The basic overloads are provided here for generic functors.
// Overloads for other custom-callables are provided in the
// internal/custom/gmock-generated-actions.h header.
template <typename F, typename... Args>
auto InvokeArgument(F f, Args... args) -> decltype(f(args...)) {
return f(args...);
}

template <std::size_t index, typename... Params>
struct InvokeArgumentAction {
template <typename... Args>
auto operator()(Args&&... args) const -> decltype(internal::InvokeArgument(
std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
std::declval<const Params&>()...)) {
internal::FlatTuple<Args&&...> args_tuple(std::forward<Args>(args)...);
return params.Apply([&](const Params&... unpacked_params) {
auto&& callable = args_tuple.template Get<index>();
return internal::InvokeArgument(
std::forward<decltype(callable)>(callable), unpacked_params...);
});
}

internal::FlatTuple<Params...> params;
};

} // namespace internal

// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
// (0-based) argument, which must be a k-ary callable, of the mock
// function, with arguments a1, a2, ..., a_k.
//
// Notes:
//
// 1. The arguments are passed by value by default. If you need to
// pass an argument by reference, wrap it inside ByRef(). For
// pass an argument by reference, wrap it inside std::ref(). For
// example,
//
// InvokeArgument<1>(5, string("Hello"), ByRef(foo))
// InvokeArgument<1>(5, string("Hello"), std::ref(foo))
//
// passes 5 and string("Hello") by value, and passes foo by
// reference.
//
// 2. If the callable takes an argument by reference but ByRef() is
// 2. If the callable takes an argument by reference but std::ref() is
// not used, it will receive the reference to a copy of the value,
// instead of the original value. For example, when the 0-th
// argument of the mock function takes a const string&, the action
Expand All @@ -534,75 +560,11 @@ namespace testing {
// to the callable. This makes it easy for a user to define an
// InvokeArgument action from temporary values and have it performed
// later.

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_0_VALUE_PARAMS()) {
return internal::InvokeArgument(::std::get<k>(args));
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(p0)) {
return internal::InvokeArgument(::std::get<k>(args), p0);
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_2_VALUE_PARAMS(p0, p1)) {
return internal::InvokeArgument(::std::get<k>(args), p0, p1);
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_3_VALUE_PARAMS(p0, p1, p2)) {
return internal::InvokeArgument(::std::get<k>(args), p0, p1, p2);
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_4_VALUE_PARAMS(p0, p1, p2, p3)) {
return internal::InvokeArgument(::std::get<k>(args), p0, p1, p2, p3);
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) {
return internal::InvokeArgument(::std::get<k>(args), p0, p1, p2, p3, p4);
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) {
return internal::InvokeArgument(::std::get<k>(args), p0, p1, p2, p3, p4, p5);
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) {
return internal::InvokeArgument(::std::get<k>(args), p0, p1, p2, p3, p4, p5,
p6);
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) {
return internal::InvokeArgument(::std::get<k>(args), p0, p1, p2, p3, p4, p5,
p6, p7);
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) {
return internal::InvokeArgument(::std::get<k>(args), p0, p1, p2, p3, p4, p5,
p6, p7, p8);
}

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) {
return internal::InvokeArgument(::std::get<k>(args), p0, p1, p2, p3, p4, p5,
p6, p7, p8, p9);
template <std::size_t index, typename... Params>
internal::InvokeArgumentAction<index, typename std::decay<Params>::type...>
InvokeArgument(Params&&... params) {
return {internal::FlatTuple<typename std::decay<Params>::type...>(
std::forward<Params>(params)...)};
}

#ifdef _MSC_VER
Expand Down
56 changes: 38 additions & 18 deletions googlemock/include/gmock/gmock-generated-actions.h.pump
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,8 @@ $range k 0..n-1
gmock_PerformImpl(\
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const


namespace testing {


// The ACTION*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
Expand All @@ -319,24 +317,52 @@ namespace testing {
# pragma warning(disable:4100)
#endif

// Various overloads for InvokeArgument<N>().
//
namespace internal {

// internal::InvokeArgument - a helper for InvokeArgument action.
// The basic overloads are provided here for generic functors.
// Overloads for other custom-callables are provided in the
// internal/custom/gmock-generated-actions.h header.
template <typename F, typename... Args>
auto InvokeArgument(F f, Args... args) -> decltype(f(args...)) {
return f(args...);
}

template <std::size_t index, typename... Params>
struct InvokeArgumentAction {
template <typename... Args>
auto operator()(Args&&... args) const -> decltype(internal::InvokeArgument(
std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
std::declval<const Params&>()...)) {
internal::FlatTuple<Args&&...> args_tuple(std::forward<Args>(args)...);
return params.Apply([&](const Params&... unpacked_params) {
auto&& callable = args_tuple.template Get<index>();
return internal::InvokeArgument(
std::forward<decltype(callable)>(callable), unpacked_params...);
});
}

internal::FlatTuple<Params...> params;
};

} // namespace internal

// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
// (0-based) argument, which must be a k-ary callable, of the mock
// function, with arguments a1, a2, ..., a_k.
//
// Notes:
//
// 1. The arguments are passed by value by default. If you need to
// pass an argument by reference, wrap it inside ByRef(). For
// pass an argument by reference, wrap it inside std::ref(). For
// example,
//
// InvokeArgument<1>(5, string("Hello"), ByRef(foo))
// InvokeArgument<1>(5, string("Hello"), std::ref(foo))
//
// passes 5 and string("Hello") by value, and passes foo by
// reference.
//
// 2. If the callable takes an argument by reference but ByRef() is
// 2. If the callable takes an argument by reference but std::ref() is
// not used, it will receive the reference to a copy of the value,
// instead of the original value. For example, when the 0-th
// argument of the mock function takes a const string&, the action
Expand All @@ -348,19 +374,13 @@ namespace testing {
// to the callable. This makes it easy for a user to define an
// InvokeArgument action from temporary values and have it performed
// later.

$range i 0..n
$for i [[
$range j 0..i-1

ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) {
return internal::InvokeArgument(::std::get<k>(args)$for j[[, p$j]]);
template <std::size_t index, typename... Params>
internal::InvokeArgumentAction<index, typename std::decay<Params>::type...>
InvokeArgument(Params&&... params) {
return {internal::FlatTuple<typename std::decay<Params>::type...>(
std::forward<Params>(params)...)};
}

]]

#ifdef _MSC_VER
# pragma warning(pop)
#endif
Expand Down

0 comments on commit 710f9c1

Please sign in to comment.