diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index 02b17c7d9d..f95be3f036 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -1539,15 +1539,6 @@ class ActionImpl> { std::tuple 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 -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_ \ diff --git a/googlemock/include/gmock/gmock-generated-actions.h b/googlemock/include/gmock/gmock-generated-actions.h index 124bd01125..844651357b 100644 --- a/googlemock/include/gmock/gmock-generated-actions.h +++ b/googlemock/include/gmock/gmock-generated-actions.h @@ -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 @@ -505,8 +503,36 @@ namespace testing { # pragma warning(disable:4100) #endif -// Various overloads for InvokeArgument(). -// +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 +auto InvokeArgument(F f, Args... args) -> decltype(f(args...)) { + return f(args...); +} + +template +struct InvokeArgumentAction { + template + auto operator()(Args&&... args) const -> decltype(internal::InvokeArgument( + std::get(std::forward_as_tuple(std::forward(args)...)), + std::declval()...)) { + internal::FlatTuple args_tuple(std::forward(args)...); + return params.Apply([&](const Params&... unpacked_params) { + auto&& callable = args_tuple.template Get(); + return internal::InvokeArgument( + std::forward(callable), unpacked_params...); + }); + } + + internal::FlatTuple params; +}; + +} // namespace internal + // The InvokeArgument(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. @@ -514,15 +540,15 @@ namespace testing { // 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 @@ -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(args)); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_1_VALUE_PARAMS(p0)) { - return internal::InvokeArgument(::std::get(args), p0); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_2_VALUE_PARAMS(p0, p1)) { - return internal::InvokeArgument(::std::get(args), p0, p1); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_3_VALUE_PARAMS(p0, p1, p2)) { - return internal::InvokeArgument(::std::get(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(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(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(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(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(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(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(args), p0, p1, p2, p3, p4, p5, - p6, p7, p8, p9); +template +internal::InvokeArgumentAction::type...> +InvokeArgument(Params&&... params) { + return {internal::FlatTuple::type...>( + std::forward(params)...)}; } #ifdef _MSC_VER diff --git a/googlemock/include/gmock/gmock-generated-actions.h.pump b/googlemock/include/gmock/gmock-generated-actions.h.pump index 7a7fc9f449..0bdb42e6f5 100644 --- a/googlemock/include/gmock/gmock-generated-actions.h.pump +++ b/googlemock/include/gmock/gmock-generated-actions.h.pump @@ -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 @@ -319,8 +317,36 @@ namespace testing { # pragma warning(disable:4100) #endif -// Various overloads for InvokeArgument(). -// +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 +auto InvokeArgument(F f, Args... args) -> decltype(f(args...)) { + return f(args...); +} + +template +struct InvokeArgumentAction { + template + auto operator()(Args&&... args) const -> decltype(internal::InvokeArgument( + std::get(std::forward_as_tuple(std::forward(args)...)), + std::declval()...)) { + internal::FlatTuple args_tuple(std::forward(args)...); + return params.Apply([&](const Params&... unpacked_params) { + auto&& callable = args_tuple.template Get(); + return internal::InvokeArgument( + std::forward(callable), unpacked_params...); + }); + } + + internal::FlatTuple params; +}; + +} // namespace internal + // The InvokeArgument(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. @@ -328,15 +354,15 @@ namespace testing { // 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 @@ -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(args)$for j[[, p$j]]); +template +internal::InvokeArgumentAction::type...> +InvokeArgument(Params&&... params) { + return {internal::FlatTuple::type...>( + std::forward(params)...)}; } -]] - #ifdef _MSC_VER # pragma warning(pop) #endif