$$ -*- mode: c++; -*- $$ This is a Pump source file. Please use Pump to convert it to $$ gmock-generated-actions.h. $$ $var n = 10 $$ The maximum arity we support. $$}} This meta comment fixes auto-indentation in editors. // Copyright 2007, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Google Mock - a framework for writing C++ mock classes. // // This file implements some commonly used variadic actions. // GOOGLETEST_CM0002 DO NOT DELETE #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ #include #include #include "gmock/gmock-actions.h" #include "gmock/internal/gmock-port.h" // Include any custom callback actions added by the local installation. #include "gmock/internal/custom/gmock-generated-actions.h" $range i 0..n $range k 0..n-1 // Sometimes you want to give an action explicit template parameters // that cannot be inferred from its value parameters. ACTION() and // ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that // and can be viewed as an extension to ACTION() and ACTION_P*(). // // The syntax: // // ACTION_TEMPLATE(ActionName, // HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m), // AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; } // // defines an action template that takes m explicit template // parameters and n value parameters. name_i is the name of the i-th // template parameter, and kind_i specifies whether it's a typename, // an integral constant, or a template. p_i is the name of the i-th // value parameter. // // Example: // // // DuplicateArg(output) converts the k-th argument of the mock // // function to type T and copies it to *output. // ACTION_TEMPLATE(DuplicateArg, // HAS_2_TEMPLATE_PARAMS(int, k, typename, T), // AND_1_VALUE_PARAMS(output)) { // *output = T(::std::get(args)); // } // ... // int n; // EXPECT_CALL(mock, Foo(_, _)) // .WillOnce(DuplicateArg<1, unsigned char>(&n)); // // To create an instance of an action template, write: // // ActionName(v1, ..., v_n) // // where the ts are the template arguments and the vs are the value // arguments. The value argument types are inferred by the compiler. // If you want to explicitly specify the value argument types, you can // provide additional template arguments: // // ActionName(v1, ..., v_n) // // where u_i is the desired type of v_i. // // ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the // number of value parameters, but not on the number of template // parameters. Without the restriction, the meaning of the following // is unclear: // // OverloadedAction(x); // // Are we using a single-template-parameter action where 'bool' refers // to the type of x, or are we using a two-template-parameter action // where the compiler is asked to infer the type of x? // // Implementation notes: // // GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and // GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for // implementing ACTION_TEMPLATE. The main trick we use is to create // new macro invocations when expanding a macro. For example, we have // // #define ACTION_TEMPLATE(name, template_params, value_params) // ... GMOCK_INTERNAL_DECL_##template_params ... // // which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...) // to expand to // // ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ... // // Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the // preprocessor will continue to expand it to // // ... typename T ... // // This technique conforms to the C++ standard and is portable. It // allows us to implement action templates using O(N) code, where N is // the maximum number of template/value parameters supported. Without // using it, we'd have to devote O(N^2) amount of code to implement all // combinations of m and n. // Declares the template parameters. $range j 1..n $for j [[ $range m 0..j-1 #define GMOCK_INTERNAL_DECL_HAS_$j[[]] _TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[kind$m name$m]] ]] // Lists the template parameters. $for j [[ $range m 0..j-1 #define GMOCK_INTERNAL_LIST_HAS_$j[[]] _TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[name$m]] ]] // Declares the types of value parameters. $for i [[ $range j 0..i-1 #define GMOCK_INTERNAL_DECL_TYPE_AND_$i[[]] _VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]] ]] // Initializes the value parameters. $for i [[ $range j 0..i-1 #define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\ ($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(::std::move(gmock_p$j))]] ]] // Defines the copy constructor $for i [[ #define GMOCK_INTERNAL_DEFN_COPY_AND_$i[[]]_VALUE_PARAMS$if i == 0[[() \ noexcept {} // Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134 ]] $else [[(...) = default;]] ]] // Declares the fields for storing the value parameters. $for i [[ $range j 0..i-1 #define GMOCK_INTERNAL_DEFN_AND_$i[[]] _VALUE_PARAMS($for j, [[p$j]]) $for j [[p$j##_type p$j; ]] ]] // Lists the value parameters. $for i [[ $range j 0..i-1 #define GMOCK_INTERNAL_LIST_AND_$i[[]] _VALUE_PARAMS($for j, [[p$j]]) $for j, [[p$j]] ]] // Lists the value parameter types. $for i [[ $range j 0..i-1 #define GMOCK_INTERNAL_LIST_TYPE_AND_$i[[]] _VALUE_PARAMS($for j, [[p$j]]) $for j [[, p$j##_type]] ]] // Declares the value parameters. $for i [[ $range j 0..i-1 #define GMOCK_INTERNAL_DECL_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]] $for j, [[p$j##_type p$j]] ]] // The suffix of the class template implementing the action template. $for i [[ $range j 0..i-1 #define GMOCK_INTERNAL_COUNT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]] $if i==1 [[P]] $elif i>=2 [[P$i]] ]] // The name of the class template implementing the action template. #define GMOCK_ACTION_CLASS_(name, value_params)\ GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params) $range k 0..n-1 #define ACTION_TEMPLATE(name, template_params, value_params) \ template \ 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_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 \ operator ::testing::Action() const { \ return GMOCK_PP_IF( \ GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \ (::testing::internal::MakeAction()), \ (::testing::internal::MakeAction(impl_))); \ } \ private: \ class gmock_Impl { \ public: \ explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {} \ template \ 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 impl_;) \ }; \ template \ 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 \ 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 \ template \ 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 { // 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 // is expanded and macro expansion cannot contain #pragma. Therefore // we suppress them here. #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable:4100) #endif 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. // // Notes: // // 1. The arguments are passed by value by default. If you need to // pass an argument by reference, wrap it inside std::ref(). For // example, // // 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 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 // // InvokeArgument<0>(string("Hello")) // // makes a copy of the temporary string("Hello") object and passes a // reference of the copy, instead of the original temporary object, // to the callable. This makes it easy for a user to define an // InvokeArgument action from temporary values and have it performed // later. template internal::InvokeArgumentAction::type...> InvokeArgument(Params&&... params) { return {internal::FlatTuple::type...>( std::forward(params)...)}; } #ifdef _MSC_VER # pragma warning(pop) #endif } // namespace testing #endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_