diff options
author | zhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386> | 2009-05-14 20:55:30 +0000 |
---|---|---|
committer | zhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386> | 2009-05-14 20:55:30 +0000 |
commit | 16cf473930c01cd7a1a51dff65f22c541fbad5b8 (patch) | |
tree | 5d286c8a70d91a0f100523f64ad17d316e8f25f7 /include | |
parent | c6a412397bc98f120d5e79d4a64e3972854b5af3 (diff) | |
download | googletest-16cf473930c01cd7a1a51dff65f22c541fbad5b8.tar.gz googletest-16cf473930c01cd7a1a51dff65f22c541fbad5b8.tar.bz2 googletest-16cf473930c01cd7a1a51dff65f22c541fbad5b8.zip |
Finishes SafeMatcherCast by catching lossy arithmetic conversions at compile-time; uses ACTION_TEMPLATE to simplify the definition of many actions; makes mock object uncopyable; teaches gmock doctor about wrong MOCK_METHODn.
Diffstat (limited to 'include')
-rw-r--r-- | include/gmock/gmock-generated-actions.h | 890 | ||||
-rw-r--r-- | include/gmock/gmock-generated-actions.h.pump | 290 | ||||
-rw-r--r-- | include/gmock/gmock-matchers.h | 17 | ||||
-rw-r--r-- | include/gmock/gmock-printers.h | 11 | ||||
-rw-r--r-- | include/gmock/gmock-spec-builders.h | 14 | ||||
-rw-r--r-- | include/gmock/internal/gmock-internal-utils.h | 157 |
6 files changed, 437 insertions, 942 deletions
diff --git a/include/gmock/gmock-generated-actions.h b/include/gmock/gmock-generated-actions.h index 6d49c600..fa02faaa 100644 --- a/include/gmock/gmock-generated-actions.h +++ b/include/gmock/gmock-generated-actions.h @@ -443,264 +443,6 @@ class CallableHelper { }; // class CallableHelper -// Invokes a nullary callable argument. -template <size_t N> -class InvokeArgumentAction0 { - public: - template <typename Result, typename ArgumentTuple> - static Result Perform(const ArgumentTuple& args) { - return CallableHelper<Result>::Call(::std::tr1::get<N>(args)); - } -}; - -// Invokes a unary callable argument with the given argument. -template <size_t N, typename A1> -class InvokeArgumentAction1 { - public: - // We deliberately pass a1 by value instead of const reference here - // in case it is a C-string literal. - // - // Since this function is defined inline, the compiler can get rid - // of the copying of the arguments. Therefore the performance won't - // be hurt. - explicit InvokeArgumentAction1(A1 a1) : arg1_(a1) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - return CallableHelper<Result>::Call(::std::tr1::get<N>(args), arg1_); - } - private: - const A1 arg1_; -}; - -// Invokes a binary callable argument with the given arguments. -template <size_t N, typename A1, typename A2> -class InvokeArgumentAction2 { - public: - InvokeArgumentAction2(A1 a1, A2 a2) : - arg1_(a1), arg2_(a2) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - return CallableHelper<Result>::Call(::std::tr1::get<N>(args), arg1_, arg2_); - } - private: - const A1 arg1_; - const A2 arg2_; -}; - -// Invokes a ternary callable argument with the given arguments. -template <size_t N, typename A1, typename A2, typename A3> -class InvokeArgumentAction3 { - public: - InvokeArgumentAction3(A1 a1, A2 a2, A3 a3) : - arg1_(a1), arg2_(a2), arg3_(a3) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - return CallableHelper<Result>::Call(::std::tr1::get<N>(args), arg1_, arg2_, - arg3_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; -}; - -// Invokes a 4-ary callable argument with the given arguments. -template <size_t N, typename A1, typename A2, typename A3, typename A4> -class InvokeArgumentAction4 { - public: - InvokeArgumentAction4(A1 a1, A2 a2, A3 a3, A4 a4) : - arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - return CallableHelper<Result>::Call(::std::tr1::get<N>(args), arg1_, arg2_, - arg3_, arg4_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; -}; - -// Invokes a 5-ary callable argument with the given arguments. -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5> -class InvokeArgumentAction5 { - public: - InvokeArgumentAction5(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : - arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - // We extract the callable to a variable before invoking it, in - // case it is a functor passed by value and its operator() is not - // const. - typename ::std::tr1::tuple_element<N, ArgumentTuple>::type function = - ::std::tr1::get<N>(args); - return function(arg1_, arg2_, arg3_, arg4_, arg5_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; -}; - -// Invokes a 6-ary callable argument with the given arguments. -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6> -class InvokeArgumentAction6 { - public: - InvokeArgumentAction6(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : - arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), arg6_(a6) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - // We extract the callable to a variable before invoking it, in - // case it is a functor passed by value and its operator() is not - // const. - typename ::std::tr1::tuple_element<N, ArgumentTuple>::type function = - ::std::tr1::get<N>(args); - return function(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; -}; - -// Invokes a 7-ary callable argument with the given arguments. -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7> -class InvokeArgumentAction7 { - public: - InvokeArgumentAction7(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : - arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), arg6_(a6), - arg7_(a7) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - // We extract the callable to a variable before invoking it, in - // case it is a functor passed by value and its operator() is not - // const. - typename ::std::tr1::tuple_element<N, ArgumentTuple>::type function = - ::std::tr1::get<N>(args); - return function(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_, arg7_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; - const A7 arg7_; -}; - -// Invokes a 8-ary callable argument with the given arguments. -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8> -class InvokeArgumentAction8 { - public: - InvokeArgumentAction8(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, - A8 a8) : - arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), arg6_(a6), - arg7_(a7), arg8_(a8) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - // We extract the callable to a variable before invoking it, in - // case it is a functor passed by value and its operator() is not - // const. - typename ::std::tr1::tuple_element<N, ArgumentTuple>::type function = - ::std::tr1::get<N>(args); - return function(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_, arg7_, arg8_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; - const A7 arg7_; - const A8 arg8_; -}; - -// Invokes a 9-ary callable argument with the given arguments. -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8, typename A9> -class InvokeArgumentAction9 { - public: - InvokeArgumentAction9(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, - A9 a9) : - arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), arg6_(a6), - arg7_(a7), arg8_(a8), arg9_(a9) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - // We extract the callable to a variable before invoking it, in - // case it is a functor passed by value and its operator() is not - // const. - typename ::std::tr1::tuple_element<N, ArgumentTuple>::type function = - ::std::tr1::get<N>(args); - return function(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_, arg7_, arg8_, - arg9_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; - const A7 arg7_; - const A8 arg8_; - const A9 arg9_; -}; - -// Invokes a 10-ary callable argument with the given arguments. -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8, typename A9, - typename A10> -class InvokeArgumentAction10 { - public: - InvokeArgumentAction10(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, - A8 a8, A9 a9, A10 a10) : - arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), arg6_(a6), - arg7_(a7), arg8_(a8), arg9_(a9), arg10_(a10) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - // We extract the callable to a variable before invoking it, in - // case it is a functor passed by value and its operator() is not - // const. - typename ::std::tr1::tuple_element<N, ArgumentTuple>::type function = - ::std::tr1::get<N>(args); - return function(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_, arg7_, arg8_, - arg9_, arg10_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; - const A7 arg7_; - const A8 arg8_; - const A9 arg9_; - const A10 arg10_; -}; - // An INTERNAL macro for extracting the type of a tuple field. It's // subject to change without notice - DO NOT USE IN USER CODE! #define GMOCK_FIELD_(Tuple, N) \ @@ -1140,140 +882,6 @@ inline internal::ReferenceWrapper<T> ByRef(T& l_value) { // NOLINT return internal::ReferenceWrapper<T>(l_value); } -// Various overloads for InvokeArgument<N>(). -// -// 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 -// example, -// -// InvokeArgument<1>(5, string("Hello"), ByRef(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 -// 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 <size_t N> -inline PolymorphicAction<internal::InvokeArgumentAction0<N> > InvokeArgument() { - return MakePolymorphicAction(internal::InvokeArgumentAction0<N>()); -} - -// We deliberately pass a1 by value instead of const reference here in -// case it is a C-string literal. If we had declared the parameter as -// 'const A1& a1' and write InvokeArgument<0>("Hi"), the compiler -// would've thought A1 is 'char[3]', which causes trouble as the -// implementation needs to copy a value of type A1. By declaring the -// parameter as 'A1 a1', the compiler will correctly infer that A1 is -// 'const char*' when it sees InvokeArgument<0>("Hi"). -// -// Since this function is defined inline, the compiler can get rid of -// the copying of the arguments. Therefore the performance won't be -// hurt. -template <size_t N, typename A1> -inline PolymorphicAction<internal::InvokeArgumentAction1<N, A1> > -InvokeArgument(A1 a1) { - return MakePolymorphicAction(internal::InvokeArgumentAction1<N, A1>(a1)); -} - -template <size_t N, typename A1, typename A2> -inline PolymorphicAction<internal::InvokeArgumentAction2<N, A1, A2> > -InvokeArgument(A1 a1, A2 a2) { - return MakePolymorphicAction( - internal::InvokeArgumentAction2<N, A1, A2>(a1, a2)); -} - -template <size_t N, typename A1, typename A2, typename A3> -inline PolymorphicAction<internal::InvokeArgumentAction3<N, A1, A2, A3> > -InvokeArgument(A1 a1, A2 a2, A3 a3) { - return MakePolymorphicAction( - internal::InvokeArgumentAction3<N, A1, A2, A3>(a1, a2, a3)); -} - -template <size_t N, typename A1, typename A2, typename A3, typename A4> -inline PolymorphicAction<internal::InvokeArgumentAction4<N, A1, A2, A3, A4> > -InvokeArgument(A1 a1, A2 a2, A3 a3, A4 a4) { - return MakePolymorphicAction( - internal::InvokeArgumentAction4<N, A1, A2, A3, A4>(a1, a2, a3, a4)); -} - -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5> -inline PolymorphicAction<internal::InvokeArgumentAction5<N, A1, A2, A3, A4, - A5> > -InvokeArgument(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return MakePolymorphicAction( - internal::InvokeArgumentAction5<N, A1, A2, A3, A4, A5>(a1, a2, a3, a4, - a5)); -} - -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6> -inline PolymorphicAction<internal::InvokeArgumentAction6<N, A1, A2, A3, A4, A5, - A6> > -InvokeArgument(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - return MakePolymorphicAction( - internal::InvokeArgumentAction6<N, A1, A2, A3, A4, A5, A6>(a1, a2, a3, - a4, a5, a6)); -} - -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7> -inline PolymorphicAction<internal::InvokeArgumentAction7<N, A1, A2, A3, A4, A5, - A6, A7> > -InvokeArgument(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { - return MakePolymorphicAction( - internal::InvokeArgumentAction7<N, A1, A2, A3, A4, A5, A6, A7>(a1, a2, - a3, a4, a5, a6, a7)); -} - -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8> -inline PolymorphicAction<internal::InvokeArgumentAction8<N, A1, A2, A3, A4, A5, - A6, A7, A8> > -InvokeArgument(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { - return MakePolymorphicAction( - internal::InvokeArgumentAction8<N, A1, A2, A3, A4, A5, A6, A7, A8>(a1, - a2, a3, a4, a5, a6, a7, a8)); -} - -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8, typename A9> -inline PolymorphicAction<internal::InvokeArgumentAction9<N, A1, A2, A3, A4, A5, - A6, A7, A8, A9> > -InvokeArgument(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { - return MakePolymorphicAction( - internal::InvokeArgumentAction9<N, A1, A2, A3, A4, A5, A6, A7, A8, - A9>(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} - -template <size_t N, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8, typename A9, - typename A10> -inline PolymorphicAction<internal::InvokeArgumentAction10<N, A1, A2, A3, A4, - A5, A6, A7, A8, A9, A10> > -InvokeArgument(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, - A10 a10) { - return MakePolymorphicAction( - internal::InvokeArgumentAction10<N, A1, A2, A3, A4, A5, A6, A7, A8, A9, - A10>(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); -} - // WithoutArgs(inner_action) can be used in a mock function with a // non-empty argument list to perform inner_action, which takes no // argument. In other words, it adapts an action accepting no @@ -2715,271 +2323,153 @@ DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6, // updated. namespace testing { -namespace internal { - -// Saves argument #0 to where the pointer points. -ACTION_P(SaveArg0, pointer) { *pointer = arg0; } +// Various overloads for InvokeArgument<N>(). +// +// 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 +// example, +// +// InvokeArgument<1>(5, string("Hello"), ByRef(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 +// 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. -// Assigns 'value' to the variable referenced by argument #0. -ACTION_P(SetArg0Referee, value) { - // Ensures that argument #0 is a reference. If you get a compiler - // error on the next line, you are using SetArgReferee<k>(value) in - // a mock function whose k-th (0-based) argument is not a reference. - GMOCK_COMPILE_ASSERT_(internal::is_reference<arg0_type>::value, - SetArgReferee_must_be_used_with_a_reference_argument); - arg0 = value; +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_0_VALUE_PARAMS()) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args)); } -// ReturnNewAction<T> creates and returns a new instance of an object each time -// it is performed. It is overloaded to work with constructors that take -// different numbers of arguments. -// Returns a new instance of T using a nullary constructor with the given -// arguments. -template <typename T> -class ReturnNewAction0 { - public: - ReturnNewAction0() {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(); - } - private: -}; - -// Returns a new instance of T using a unary constructor with the given -// arguments. -template <typename T, typename A1> -class ReturnNewAction1 { - public: - explicit ReturnNewAction1(A1 a1) : arg1_(a1) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_); - } - private: - const A1 arg1_; -}; - -// Returns a new instance of T using a binary constructor with the given -// arguments. -template <typename T, typename A1, typename A2> -class ReturnNewAction2 { - public: - ReturnNewAction2(A1 a1, A2 a2) : arg1_(a1), arg2_(a2) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_, arg2_); - } - private: - const A1 arg1_; - const A2 arg2_; -}; - -// Returns a new instance of T using a ternary constructor with the given -// arguments. -template <typename T, typename A1, typename A2, typename A3> -class ReturnNewAction3 { - public: - ReturnNewAction3(A1 a1, A2 a2, A3 a3) : arg1_(a1), arg2_(a2), arg3_(a3) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_, arg2_, arg3_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; -}; - -// Returns a new instance of T using a 4-ary constructor with the given -// arguments. -template <typename T, typename A1, typename A2, typename A3, typename A4> -class ReturnNewAction4 { - public: - ReturnNewAction4(A1 a1, A2 a2, A3 a3, A4 a4) : arg1_(a1), arg2_(a2), - arg3_(a3), arg4_(a4) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_, arg2_, arg3_, arg4_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; -}; - -// Returns a new instance of T using a 5-ary constructor with the given -// arguments. -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5> -class ReturnNewAction5 { - public: - ReturnNewAction5(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : arg1_(a1), arg2_(a2), - arg3_(a3), arg4_(a4), arg5_(a5) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_, arg2_, arg3_, arg4_, arg5_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; -}; - -// Returns a new instance of T using a 6-ary constructor with the given -// arguments. -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6> -class ReturnNewAction6 { - public: - ReturnNewAction6(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : arg1_(a1), - arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), arg6_(a6) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; -}; - -// Returns a new instance of T using a 7-ary constructor with the given -// arguments. -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7> -class ReturnNewAction7 { - public: - ReturnNewAction7(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, - A7 a7) : arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), - arg6_(a6), arg7_(a7) {} +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_1_VALUE_PARAMS(p0)) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0); +} - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_, arg7_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; - const A7 arg7_; -}; +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_2_VALUE_PARAMS(p0, p1)) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0, p1); +} -// Returns a new instance of T using a 8-ary constructor with the given -// arguments. -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8> -class ReturnNewAction8 { - public: - ReturnNewAction8(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, - A8 a8) : arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), - arg6_(a6), arg7_(a7), arg8_(a8) {} +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_3_VALUE_PARAMS(p0, p1, p2)) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0, p1, p2); +} - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_, arg7_, arg8_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; - const A7 arg7_; - const A8 arg8_; -}; +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_4_VALUE_PARAMS(p0, p1, p2, p3)) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0, p1, p2, p3); +} -// Returns a new instance of T using a 9-ary constructor with the given -// arguments. -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8, typename A9> -class ReturnNewAction9 { - public: - ReturnNewAction9(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, - A9 a9) : arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), - arg6_(a6), arg7_(a7), arg8_(a8), arg9_(a9) {} +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0, p1, p2, p3, p4); +} - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_, arg7_, arg8_, arg9_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; - const A7 arg7_; - const A8 arg8_; - const A9 arg9_; -}; +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5); +} -// Returns a new instance of T using a 10-ary constructor with the given -// arguments. -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8, typename A9, - typename A10> -class ReturnNewAction10 { - public: - ReturnNewAction10(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, - A9 a9, A10 a10) : arg1_(a1), arg2_(a2), arg3_(a3), arg4_(a4), arg5_(a5), - arg6_(a6), arg7_(a7), arg8_(a8), arg9_(a9), arg10_(a10) {} +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6); +} - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_, arg7_, arg8_, arg9_, - arg10_); - } - private: - const A1 arg1_; - const A2 arg2_; - const A3 arg3_; - const A4 arg4_; - const A5 arg5_; - const A6 arg6_; - const A7 arg7_; - const A8 arg8_; - const A9 arg9_; - const A10 arg10_; -}; +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7); +} -// Deletes the object pointed to by argument #0. -ACTION(DeleteArg0) { delete arg0; } +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8); +} -} // namespace internal +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::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); +} // Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the // mock function to *pointer. -template <int k, typename Pointer> -inline internal::WithArgsAction<internal::SaveArg0ActionP<Pointer>, k> -SaveArg(const Pointer& pointer) { - return WithArg<k>(internal::SaveArg0(pointer)); +ACTION_TEMPLATE(SaveArg, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_1_VALUE_PARAMS(pointer)) { + *pointer = ::std::tr1::get<k>(args); } // Action SetArgReferee<k>(value) assigns 'value' to the variable // referenced by the k-th (0-based) argument of the mock function. -template <int k, typename Value> -inline internal::WithArgsAction<internal::SetArg0RefereeActionP<Value>, k> -SetArgReferee(const Value& value) { - return WithArg<k>(internal::SetArg0Referee(value)); +ACTION_TEMPLATE(SetArgReferee, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_1_VALUE_PARAMS(value)) { + typedef typename ::std::tr1::tuple_element<k, args_type>::type argk_type; + // Ensures that argument #k is a reference. If you get a compiler + // error on the next line, you are using SetArgReferee<k>(value) in + // a mock function whose k-th (0-based) argument is not a reference. + GMOCK_COMPILE_ASSERT_(internal::is_reference<argk_type>::value, + SetArgReferee_must_be_used_with_a_reference_argument); + ::std::tr1::get<k>(args) = value; +} + +// Action SetArrayArgument<k>(first, last) copies the elements in +// source range [first, last) to the array pointed to by the k-th +// (0-based) argument, which can be either a pointer or an +// iterator. The action does not take ownership of the elements in the +// source range. +ACTION_TEMPLATE(SetArrayArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_2_VALUE_PARAMS(first, last)) { + // Microsoft compiler deprecates ::std::copy, so we want to suppress warning + // 4996 (Function call with parameters that may be unsafe) there. +#ifdef _MSC_VER +#pragma warning(push) // Saves the current warning state. +#pragma warning(disable:4996) // Temporarily disables warning 4996. +#endif + ::std::copy(first, last, ::std::tr1::get<k>(args)); +#ifdef _MSC_VER +#pragma warning(pop) // Restores the warning state. +#endif } // Various overloads for ReturnNew<T>(). @@ -2987,106 +2477,78 @@ SetArgReferee(const Value& value) { // The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new // instance of type T, constructed on the heap with constructor arguments // a1, a2, ..., and a_k. The caller assumes ownership of the returned value. -template <typename T> -inline PolymorphicAction<internal::ReturnNewAction0<T> > -ReturnNew() { - return MakePolymorphicAction( - internal::ReturnNewAction0<T>()); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_0_VALUE_PARAMS()) { + return new T(); } -template <typename T, typename A1> -inline PolymorphicAction<internal::ReturnNewAction1<T, A1> > -ReturnNew(A1 a1) { - return MakePolymorphicAction( - internal::ReturnNewAction1<T, A1>(a1)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_1_VALUE_PARAMS(p0)) { + return new T(p0); } -template <typename T, typename A1, typename A2> -inline PolymorphicAction<internal::ReturnNewAction2<T, A1, A2> > -ReturnNew(A1 a1, A2 a2) { - return MakePolymorphicAction( - internal::ReturnNewAction2<T, A1, A2>(a1, a2)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_2_VALUE_PARAMS(p0, p1)) { + return new T(p0, p1); } -template <typename T, typename A1, typename A2, typename A3> -inline PolymorphicAction<internal::ReturnNewAction3<T, A1, A2, A3> > -ReturnNew(A1 a1, A2 a2, A3 a3) { - return MakePolymorphicAction( - internal::ReturnNewAction3<T, A1, A2, A3>(a1, a2, a3)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_3_VALUE_PARAMS(p0, p1, p2)) { + return new T(p0, p1, p2); } -template <typename T, typename A1, typename A2, typename A3, typename A4> -inline PolymorphicAction<internal::ReturnNewAction4<T, A1, A2, A3, A4> > -ReturnNew(A1 a1, A2 a2, A3 a3, A4 a4) { - return MakePolymorphicAction( - internal::ReturnNewAction4<T, A1, A2, A3, A4>(a1, a2, a3, a4)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_4_VALUE_PARAMS(p0, p1, p2, p3)) { + return new T(p0, p1, p2, p3); } -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5> -inline PolymorphicAction<internal::ReturnNewAction5<T, A1, A2, A3, A4, A5> > -ReturnNew(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return MakePolymorphicAction( - internal::ReturnNewAction5<T, A1, A2, A3, A4, A5>(a1, a2, a3, a4, a5)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) { + return new T(p0, p1, p2, p3, p4); } -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6> -inline PolymorphicAction<internal::ReturnNewAction6<T, A1, A2, A3, A4, A5, A6> > -ReturnNew(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - return MakePolymorphicAction( - internal::ReturnNewAction6<T, A1, A2, A3, A4, A5, A6>(a1, a2, a3, a4, a5, - a6)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) { + return new T(p0, p1, p2, p3, p4, p5); } -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7> -inline PolymorphicAction<internal::ReturnNewAction7<T, A1, A2, A3, A4, A5, A6, - A7> > -ReturnNew(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { - return MakePolymorphicAction( - internal::ReturnNewAction7<T, A1, A2, A3, A4, A5, A6, A7>(a1, a2, a3, a4, - a5, a6, a7)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) { + return new T(p0, p1, p2, p3, p4, p5, p6); } -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8> -inline PolymorphicAction<internal::ReturnNewAction8<T, A1, A2, A3, A4, A5, A6, - A7, A8> > -ReturnNew(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { - return MakePolymorphicAction( - internal::ReturnNewAction8<T, A1, A2, A3, A4, A5, A6, A7, A8>(a1, a2, a3, - a4, a5, a6, a7, a8)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) { + return new T(p0, p1, p2, p3, p4, p5, p6, p7); } -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8, typename A9> -inline PolymorphicAction<internal::ReturnNewAction9<T, A1, A2, A3, A4, A5, A6, - A7, A8, A9> > -ReturnNew(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { - return MakePolymorphicAction( - internal::ReturnNewAction9<T, A1, A2, A3, A4, A5, A6, A7, A8, A9>(a1, a2, - a3, a4, a5, a6, a7, a8, a9)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) { + return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8); } -template <typename T, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8, typename A9, - typename A10> -inline PolymorphicAction<internal::ReturnNewAction10<T, A1, A2, A3, A4, A5, A6, - A7, A8, A9, A10> > -ReturnNew(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, - A10 a10) { - return MakePolymorphicAction( - internal::ReturnNewAction10<T, A1, A2, A3, A4, A5, A6, A7, A8, A9, - A10>(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) { + return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); } // Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock // function. -template <int k> -inline internal::WithArgsAction<internal::DeleteArg0Action, k> -DeleteArg() { - return WithArg<k>(internal::DeleteArg0()); +ACTION_TEMPLATE(DeleteArg, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_0_VALUE_PARAMS()) { + delete ::std::tr1::get<k>(args); } // Action Throw(exception) can be used in a mock function of any type diff --git a/include/gmock/gmock-generated-actions.h.pump b/include/gmock/gmock-generated-actions.h.pump index 39f80804..b5223a34 100644 --- a/include/gmock/gmock-generated-actions.h.pump +++ b/include/gmock/gmock-generated-actions.h.pump @@ -198,77 +198,6 @@ $var Ts = [[$for j, [[T$j]]]] }; // class CallableHelper -// Invokes a nullary callable argument. -template <size_t N> -class InvokeArgumentAction0 { - public: - template <typename Result, typename ArgumentTuple> - static Result Perform(const ArgumentTuple& args) { - return CallableHelper<Result>::Call(::std::tr1::get<N>(args)); - } -}; - -// Invokes a unary callable argument with the given argument. -template <size_t N, typename A1> -class InvokeArgumentAction1 { - public: - // We deliberately pass a1 by value instead of const reference here - // in case it is a C-string literal. - // - // Since this function is defined inline, the compiler can get rid - // of the copying of the arguments. Therefore the performance won't - // be hurt. - explicit InvokeArgumentAction1(A1 a1) : arg1_(a1) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { - return CallableHelper<Result>::Call(::std::tr1::get<N>(args), arg1_); - } - private: - const A1 arg1_; -}; - -$range i 2..n -$for i [[ -$var arity = [[$if i==2 [[binary]] $elif i==3 [[ternary]] $else [[$i-ary]]]] -$range j 1..i -$var typename_As = [[$for j, [[typename A$j]]]] -$var args_ = [[$for j, [[arg$j[[]]_]]]] - -// Invokes a $arity callable argument with the given arguments. -template <size_t N, $typename_As> -class InvokeArgumentAction$i { - public: - InvokeArgumentAction$i($for j, [[A$j a$j]]) : - $for j, [[arg$j[[]]_(a$j)]] {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) { -$if i <= 4 [[ - - return CallableHelper<Result>::Call(::std::tr1::get<N>(args), $args_); - -]] $else [[ - - // We extract the callable to a variable before invoking it, in - // case it is a functor passed by value and its operator() is not - // const. - typename ::std::tr1::tuple_element<N, ArgumentTuple>::type function = - ::std::tr1::get<N>(args); - return function($args_); - -]] - } - private: -$for j [[ - - const A$j arg$j[[]]_; -]] - -}; - -]] - // An INTERNAL macro for extracting the type of a tuple field. It's // subject to change without notice - DO NOT USE IN USER CODE! #define GMOCK_FIELD_(Tuple, N) \ @@ -478,74 +407,6 @@ inline internal::ReferenceWrapper<T> ByRef(T& l_value) { // NOLINT return internal::ReferenceWrapper<T>(l_value); } -// Various overloads for InvokeArgument<N>(). -// -// 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 -// example, -// -// InvokeArgument<1>(5, string("Hello"), ByRef(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 -// 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 <size_t N> -inline PolymorphicAction<internal::InvokeArgumentAction0<N> > InvokeArgument() { - return MakePolymorphicAction(internal::InvokeArgumentAction0<N>()); -} - -// We deliberately pass a1 by value instead of const reference here in -// case it is a C-string literal. If we had declared the parameter as -// 'const A1& a1' and write InvokeArgument<0>("Hi"), the compiler -// would've thought A1 is 'char[3]', which causes trouble as the -// implementation needs to copy a value of type A1. By declaring the -// parameter as 'A1 a1', the compiler will correctly infer that A1 is -// 'const char*' when it sees InvokeArgument<0>("Hi"). -// -// Since this function is defined inline, the compiler can get rid of -// the copying of the arguments. Therefore the performance won't be -// hurt. -template <size_t N, typename A1> -inline PolymorphicAction<internal::InvokeArgumentAction1<N, A1> > -InvokeArgument(A1 a1) { - return MakePolymorphicAction(internal::InvokeArgumentAction1<N, A1>(a1)); -} - -$range i 2..n -$for i [[ -$range j 1..i -$var typename_As = [[$for j, [[typename A$j]]]] -$var As = [[$for j, [[A$j]]]] -$var Aas = [[$for j, [[A$j a$j]]]] -$var as = [[$for j, [[a$j]]]] - -template <size_t N, $typename_As> -inline PolymorphicAction<internal::InvokeArgumentAction$i<N, $As> > -InvokeArgument($Aas) { - return MakePolymorphicAction( - internal::InvokeArgumentAction$i<N, $As>($as)); -} - -]] - // WithoutArgs(inner_action) can be used in a mock function with a // non-empty argument list to perform inner_action, which takes no // argument. In other words, it adapts an action accepting no @@ -1025,76 +886,89 @@ $$ // show up in the generated code. // updated. namespace testing { -namespace internal { - -// Saves argument #0 to where the pointer points. -ACTION_P(SaveArg0, pointer) { *pointer = arg0; } - -// Assigns 'value' to the variable referenced by argument #0. -ACTION_P(SetArg0Referee, value) { - // Ensures that argument #0 is a reference. If you get a compiler - // error on the next line, you are using SetArgReferee<k>(value) in - // a mock function whose k-th (0-based) argument is not a reference. - GMOCK_COMPILE_ASSERT_(internal::is_reference<arg0_type>::value, - SetArgReferee_must_be_used_with_a_reference_argument); - arg0 = value; -} +// Various overloads for InvokeArgument<N>(). +// +// 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 +// example, +// +// InvokeArgument<1>(5, string("Hello"), ByRef(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 +// 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. -// ReturnNewAction<T> creates and returns a new instance of an object each time -// it is performed. It is overloaded to work with constructors that take -// different numbers of arguments. $range i 0..n $for i [[ -$var arity = [[ $if i==0 [[nullary]] - $elif i==1 [[unary]] - $elif i==2 [[binary]] - $elif i==3 [[ternary]] - $else [[$i-ary]]]] -$range j 1..i -$var typename_As = [[$for j [[, typename A$j]]]] -$var args_ = [[$for j, [[arg$j[[]]_]]]] - -// Returns a new instance of T using a $arity constructor with the given -// arguments. -template <typename T$typename_As> -class ReturnNewAction$i { - public: - $if i==1 [[explicit ]]ReturnNewAction$i($for j, [[A$j a$j]])$if i>0 [[ : ]] -$for j, [[arg$j[[]]_(a$j)]] {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& /* args */) { - return new T($args_); - } - private: -$for j [[ - - const A$j arg$j[[]]_; -]] +$range j 0..i-1 -}; +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) { + return internal::CallableHelper<return_type>::Call( + ::std::tr1::get<k>(args)$for j [[, p$j]]); +} ]] -// Deletes the object pointed to by argument #0. -ACTION(DeleteArg0) { delete arg0; } - -} // namespace internal - // Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the // mock function to *pointer. -template <int k, typename Pointer> -inline internal::WithArgsAction<internal::SaveArg0ActionP<Pointer>, k> -SaveArg(const Pointer& pointer) { - return WithArg<k>(internal::SaveArg0(pointer)); +ACTION_TEMPLATE(SaveArg, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_1_VALUE_PARAMS(pointer)) { + *pointer = ::std::tr1::get<k>(args); } // Action SetArgReferee<k>(value) assigns 'value' to the variable // referenced by the k-th (0-based) argument of the mock function. -template <int k, typename Value> -inline internal::WithArgsAction<internal::SetArg0RefereeActionP<Value>, k> -SetArgReferee(const Value& value) { - return WithArg<k>(internal::SetArg0Referee(value)); +ACTION_TEMPLATE(SetArgReferee, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_1_VALUE_PARAMS(value)) { + typedef typename ::std::tr1::tuple_element<k, args_type>::type argk_type; + // Ensures that argument #k is a reference. If you get a compiler + // error on the next line, you are using SetArgReferee<k>(value) in + // a mock function whose k-th (0-based) argument is not a reference. + GMOCK_COMPILE_ASSERT_(internal::is_reference<argk_type>::value, + SetArgReferee_must_be_used_with_a_reference_argument); + ::std::tr1::get<k>(args) = value; +} + +// Action SetArrayArgument<k>(first, last) copies the elements in +// source range [first, last) to the array pointed to by the k-th +// (0-based) argument, which can be either a pointer or an +// iterator. The action does not take ownership of the elements in the +// source range. +ACTION_TEMPLATE(SetArrayArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_2_VALUE_PARAMS(first, last)) { + // Microsoft compiler deprecates ::std::copy, so we want to suppress warning + // 4996 (Function call with parameters that may be unsafe) there. +#ifdef _MSC_VER +#pragma warning(push) // Saves the current warning state. +#pragma warning(disable:4996) // Temporarily disables warning 4996. +#endif + ::std::copy(first, last, ::std::tr1::get<k>(args)); +#ifdef _MSC_VER +#pragma warning(pop) // Restores the warning state. +#endif } // Various overloads for ReturnNew<T>(). @@ -1104,27 +978,23 @@ SetArgReferee(const Value& value) { // a1, a2, ..., and a_k. The caller assumes ownership of the returned value. $range i 0..n $for i [[ -$range j 1..i -$var typename_As = [[$for j [[, typename A$j]]]] -$var As = [[$for j [[, A$j]]]] -$var Aas = [[$for j, [[A$j a$j]]]] -$var as = [[$for j, [[a$j]]]] +$range j 0..i-1 +$var ps = [[$for j, [[p$j]]]] -template <typename T$typename_As> -inline PolymorphicAction<internal::ReturnNewAction$i<T$As> > -ReturnNew($Aas) { - return MakePolymorphicAction( - internal::ReturnNewAction$i<T$As>($as)); +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_$i[[]]_VALUE_PARAMS($ps)) { + return new T($ps); } ]] // Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock // function. -template <int k> -inline internal::WithArgsAction<internal::DeleteArg0Action, k> -DeleteArg() { - return WithArg<k>(internal::DeleteArg0()); +ACTION_TEMPLATE(DeleteArg, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_0_VALUE_PARAMS()) { + delete ::std::tr1::get<k>(args); } // Action Throw(exception) can be used in a mock function of any type diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index bf049d45..0497be27 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -39,6 +39,7 @@ #define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ #include <algorithm> +#include <limits> #include <ostream> // NOLINT #include <sstream> #include <string> @@ -340,6 +341,16 @@ Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) { GMOCK_COMPILE_ASSERT_( internal::is_reference<T>::value || !internal::is_reference<U>::value, cannot_convert_non_referentce_arg_to_reference); + // In case both T and U are arithmetic types, enforce that the + // conversion is not lossy. + typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(T)) RawT; + typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(U)) RawU; + const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; + const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; + GMOCK_COMPILE_ASSERT_( + kTIsOther || kUIsOther || + (internal::LosslessArithmeticConvertible<RawT, RawU>::value), + conversion_of_arithmetic_types_must_be_lossless); return MatcherCast<T>(matcher); } @@ -1164,8 +1175,8 @@ class EitherOfMatcher { // both Matcher1 and Matcher2 can match. template <typename T> operator Matcher<T>() const { - return Matcher<T>(new EitherOfMatcherImpl<T>(SafeMatcherCast<T>(matcher1_), - SafeMatcherCast<T>(matcher2_))); + return Matcher<T>(new EitherOfMatcherImpl<T>( + SafeMatcherCast<T>(matcher1_), SafeMatcherCast<T>(matcher2_))); } private: Matcher1 matcher1_; @@ -1184,7 +1195,7 @@ class TrulyMatcher { // argument is passed by reference as the predicate may be // interested in the address of the argument. template <typename T> - bool Matches(T& x) const { + bool Matches(T& x) const { // NOLINT #if GTEST_OS_WINDOWS // MSVC warns about converting a value into bool (warning 4800). #pragma warning(push) // Saves the current warning state. diff --git a/include/gmock/gmock-printers.h b/include/gmock/gmock-printers.h index 6997a6c1..99002434 100644 --- a/include/gmock/gmock-printers.h +++ b/include/gmock/gmock-printers.h @@ -341,12 +341,11 @@ inline void PrintTo(char* s, ::std::ostream* os) { PrintTo(implicit_cast<const char*>(s), os); } -// MSVC compiler can be configured to define whar_t as a typedef -// of unsigned short. Defining an overload for const wchar_t* in that case -// would cause pointers to unsigned shorts be printed as wide strings, -// possibly accessing more memory than intended and causing invalid -// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when -// wchar_t is implemented as a native type. +// MSVC can be configured to define wchar_t as a typedef of unsigned +// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native +// type. When wchar_t is a typedef, defining an overload for const +// wchar_t* would cause unsigned short* be printed as a wide string, +// possibly causing invalid memory accesses. #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) // Overloads for wide C strings void PrintTo(const wchar_t* s, ::std::ostream* os); diff --git a/include/gmock/gmock-spec-builders.h b/include/gmock/gmock-spec-builders.h index af2e8ad2..cc48bc0b 100644 --- a/include/gmock/gmock-spec-builders.h +++ b/include/gmock/gmock-spec-builders.h @@ -1359,6 +1359,20 @@ class FunctionMockerBase : public UntypedFunctionMockerBase { std::vector<DefaultActionSpec<F> > default_actions_; // All expectations for this function mocker. Expectations expectations_; + + // There is no generally useful and implementable semantics of + // copying a mock object, so copying a mock is usually a user error. + // Thus we disallow copying function mockers. If the user really + // wants to copy a mock object, he should implement his own copy + // operation, for example: + // + // class MockFoo : public Foo { + // public: + // // Defines a copy constructor explicitly. + // MockFoo(const MockFoo& src) {} + // ... + // }; + GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase); }; // class FunctionMockerBase #ifdef _MSC_VER diff --git a/include/gmock/internal/gmock-internal-utils.h b/include/gmock/internal/gmock-internal-utils.h index b3d1a1d1..b02682f8 100644 --- a/include/gmock/internal/gmock-internal-utils.h +++ b/include/gmock/internal/gmock-internal-utils.h @@ -157,7 +157,7 @@ inline Element* GetRawPointer(Element* p) { return p; } // This comparator allows linked_ptr to be stored in sets. template <typename T> struct LinkedPtrLessThan { - bool operator()(const ::testing::internal::linked_ptr<T>& lhs, + bool operator()(const ::testing::internal::linked_ptr<T>& lhs, const ::testing::internal::linked_ptr<T>& rhs) const { return lhs.get() < rhs.get(); } @@ -210,17 +210,154 @@ class ImplicitlyConvertible { template <typename From, typename To> const bool ImplicitlyConvertible<From, To>::value; +// In what follows, we use the term "kind" to indicate whether a type +// is bool, an integer type (excluding bool), a floating-point type, +// or none of them. This categorization is useful for determining +// when a matcher argument type can be safely converted to another +// type in the implementation of SafeMatcherCast. +enum TypeKind { + kBool, kInteger, kFloatingPoint, kOther +}; + +// KindOf<T>::value is the kind of type T. +template <typename T> struct KindOf { + enum { value = kOther }; // The default kind. +}; + +// This macro declares that the kind of 'type' is 'kind'. +#define GMOCK_DECLARE_KIND_(type, kind) \ + template <> struct KindOf<type> { enum { value = kind }; } + +GMOCK_DECLARE_KIND_(bool, kBool); + +// All standard integer types. +GMOCK_DECLARE_KIND_(char, kInteger); +GMOCK_DECLARE_KIND_(signed char, kInteger); +GMOCK_DECLARE_KIND_(unsigned char, kInteger); +GMOCK_DECLARE_KIND_(short, kInteger); // NOLINT +GMOCK_DECLARE_KIND_(unsigned short, kInteger); // NOLINT +GMOCK_DECLARE_KIND_(int, kInteger); +GMOCK_DECLARE_KIND_(unsigned int, kInteger); +GMOCK_DECLARE_KIND_(long, kInteger); // NOLINT +GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT + +// MSVC can be configured to define wchar_t as a typedef of unsigned +// short. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t is a +// native type. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +GMOCK_DECLARE_KIND_(wchar_t, kInteger); +#endif + +// Non-standard integer types. +GMOCK_DECLARE_KIND_(Int64, kInteger); +GMOCK_DECLARE_KIND_(UInt64, kInteger); + +// All standard floating-point types. +GMOCK_DECLARE_KIND_(float, kFloatingPoint); +GMOCK_DECLARE_KIND_(double, kFloatingPoint); +GMOCK_DECLARE_KIND_(long double, kFloatingPoint); + +#undef GMOCK_DECLARE_KIND_ + +// Evaluates to the kind of 'type'. +#define GMOCK_KIND_OF_(type) \ + static_cast< ::testing::internal::TypeKind>( \ + ::testing::internal::KindOf<type>::value) + +// Evaluates to true iff integer type T is signed. +#define GMOCK_IS_SIGNED_(T) (static_cast<T>(-1) < 0) + +// LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value +// is true iff arithmetic type From can be losslessly converted to +// arithmetic type To. +// +// It's the user's responsibility to ensure that both From and To are +// raw (i.e. has no CV modifier, is not a pointer, and is not a +// reference) built-in arithmetic types, kFromKind is the kind of +// From, and kToKind is the kind of To; the value is +// implementation-defined when the above pre-condition is violated. +template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To> +struct LosslessArithmeticConvertibleImpl : public false_type {}; + +// Converting bool to bool is lossless. +template <> +struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool> + : public true_type {}; // NOLINT + +// Converting bool to any integer type is lossless. +template <typename To> +struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To> + : public true_type {}; // NOLINT + +// Converting bool to any floating-point type is lossless. +template <typename To> +struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To> + : public true_type {}; // NOLINT + +// Converting an integer to bool is lossy. +template <typename From> +struct LosslessArithmeticConvertibleImpl<kInteger, From, kBool, bool> + : public false_type {}; // NOLINT + +// Converting an integer to another non-bool integer is lossless iff +// the target type's range encloses the source type's range. +template <typename From, typename To> +struct LosslessArithmeticConvertibleImpl<kInteger, From, kInteger, To> + : public bool_constant< + // When converting from a smaller size to a larger size, we are + // fine as long as we are not converting from signed to unsigned. + ((sizeof(From) < sizeof(To)) && + (!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) || + // When converting between the same size, the signedness must match. + ((sizeof(From) == sizeof(To)) && + (GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {}; // NOLINT + +#undef GMOCK_IS_SIGNED_ + +// Converting an integer to a floating-point type may be lossy, since +// the format of a floating-point number is implementation-defined. +template <typename From, typename To> +struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To> + : public false_type {}; // NOLINT + +// Converting a floating-point to bool is lossy. +template <typename From> +struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool> + : public false_type {}; // NOLINT + +// Converting a floating-point to an integer is lossy. +template <typename From, typename To> +struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kInteger, To> + : public false_type {}; // NOLINT + +// Converting a floating-point to another floating-point is lossless +// iff the target type is at least as big as the source type. +template <typename From, typename To> +struct LosslessArithmeticConvertibleImpl< + kFloatingPoint, From, kFloatingPoint, To> + : public bool_constant<sizeof(From) <= sizeof(To)> {}; // NOLINT + +// LosslessArithmeticConvertible<From, To>::value is true iff arithmetic +// type From can be losslessly converted to arithmetic type To. +// +// It's the user's responsibility to ensure that both From and To are +// raw (i.e. has no CV modifier, is not a pointer, and is not a +// reference) built-in arithmetic types; the value is +// implementation-defined when the above pre-condition is violated. +template <typename From, typename To> +struct LosslessArithmeticConvertible + : public LosslessArithmeticConvertibleImpl< + GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {}; // NOLINT + // IsAProtocolMessage<T>::value is a compile-time bool constant that's // true iff T is type ProtocolMessage, proto2::Message, or a subclass // of those. template <typename T> -struct IsAProtocolMessage { - static const bool value = - ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value || - ImplicitlyConvertible<const T*, const ::proto2::Message*>::value; +struct IsAProtocolMessage + : public bool_constant< + ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value || + ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> { }; -template <typename T> -const bool IsAProtocolMessage<T>::value; // When the compiler sees expression IsContainerTest<C>(0), the first // overload of IsContainerTest will be picked if C is an STL-style @@ -314,6 +451,8 @@ void Log(LogSeverity severity, const string& message, int stack_frames_to_skip); // to declare an unused << operator in the global namespace. struct Unused {}; +// TODO(wan@google.com): group all type utilities together. + // Type traits. // is_reference<T>::value is non-zero iff T is a reference type. @@ -325,8 +464,8 @@ template <typename T1, typename T2> struct type_equals : public false_type {}; template <typename T> struct type_equals<T, T> : public true_type {}; // remove_reference<T>::type removes the reference from type T, if any. -template <typename T> struct remove_reference { typedef T type; }; -template <typename T> struct remove_reference<T&> { typedef T type; }; +template <typename T> struct remove_reference { typedef T type; }; // NOLINT +template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT // Invalid<T>() returns an invalid value of type T. This is useful // when a value of type T is needed for compilation, but the statement |