From 8654c1ca10a1fff1ab6778bc0a4545b3e68c7f41 Mon Sep 17 00:00:00 2001 From: Gennadiy Civil Date: Wed, 11 Apr 2018 15:33:31 -0400 Subject: [PATCH 1/2] merging --- googlemock/include/gmock/gmock-actions.h | 90 +++++++++++++++++++----- 1 file changed, 73 insertions(+), 17 deletions(-) diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index 90fd2ea6..a2784f63 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -360,15 +360,21 @@ class Action { // Constructs a null Action. Needed for storing Action objects in // STL containers. - Action() : impl_(NULL) {} + Action() {} - // Constructs an Action from its implementation. A NULL impl is - // used to represent the "do-default" action. +#if GTEST_LANG_CXX11 + // Construct an Action from a specified callable. + // This cannot take std::function directly, because then Action would not be + // directly constructible from lambda (it would require two conversions). + template , G>::value>::type> + Action(G&& fun) : fun_(::std::forward(fun)) {} // NOLINT +#endif + + // Constructs an Action from its implementation. explicit Action(ActionInterface* impl) : impl_(impl) {} - // Copy constructor. - Action(const Action& action) : impl_(action.impl_) {} - // This constructor allows us to turn an Action object into an // Action, as long as F's arguments can be implicitly converted // to Func's and Func's return type can be implicitly converted to @@ -377,7 +383,13 @@ class Action { explicit Action(const Action& action); // Returns true iff this is the DoDefault() action. - bool IsDoDefault() const { return impl_.get() == NULL; } + bool IsDoDefault() const { +#if GTEST_LANG_CXX11 + return impl_ == nullptr && fun_ == nullptr; +#else + return impl_ == NULL; +#endif + } // Performs the action. Note that this method is const even though // the corresponding method in ActionInterface is not. The reason @@ -385,14 +397,15 @@ class Action { // another concrete action, not that the concrete action it binds to // cannot change state. (Think of the difference between a const // pointer and a pointer to const.) - Result Perform(const ArgumentTuple& args) const { - internal::Assert( - !IsDoDefault(), __FILE__, __LINE__, - "You are using DoDefault() inside a composite action like " - "DoAll() or WithArgs(). This is not supported for technical " - "reasons. Please instead spell out the default action, or " - "assign the default action to an Action variable and use " - "the variable in various places."); + Result Perform(ArgumentTuple args) const { + if (IsDoDefault()) { + internal::IllegalDoDefault(__FILE__, __LINE__); + } +#if GTEST_LANG_CXX11 + if (fun_ != nullptr) { + return internal::Apply(fun_, ::std::move(args)); + } +#endif return impl_->Perform(args); } @@ -400,6 +413,18 @@ class Action { template friend class internal::ActionAdaptor; + template + friend class Action; + + // In C++11, Action can be implemented either as a generic functor (through + // std::function), or legacy ActionInterface. In C++98, only ActionInterface + // is available. The invariants are as follows: + // * in C++98, impl_ is null iff this is the default action + // * in C++11, at most one of fun_ & impl_ may be nonnull; both are null iff + // this is the default action +#if GTEST_LANG_CXX11 + ::std::function fun_; +#endif internal::linked_ptr > impl_; }; @@ -531,6 +556,9 @@ struct ByMoveWrapper { // statement, and conversion of the result of Return to Action is a // good place for that. // +// The real life example of the above scenario happens when an invocation +// of gtl::Container() is passed into Return. +// template class ReturnAction { public: @@ -750,7 +778,7 @@ class DoDefaultAction { // This template type conversion operator allows DoDefault() to be // used in any function. template - operator Action() const { return Action(NULL); } + operator Action() const { return Action(); } // NOLINT }; // Implements the Assign action to set a given pointer referent to a @@ -886,6 +914,28 @@ class InvokeMethodWithoutArgsAction { GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction); }; +// Implements the InvokeWithoutArgs(callback) action. +template +class InvokeCallbackWithoutArgsAction { + public: + // The c'tor takes ownership of the callback. + explicit InvokeCallbackWithoutArgsAction(CallbackType* callback) + : callback_(callback) { + callback->CheckIsRepeatable(); // Makes sure the callback is permanent. + } + + // This type conversion operator template allows Invoke(callback) to + // be used wherever the callback's return type can be implicitly + // converted to that of the mock function. + template + Result Perform(const ArgumentTuple&) const { return callback_->Run(); } + + private: + const internal::linked_ptr callback_; + + GTEST_DISALLOW_ASSIGN_(InvokeCallbackWithoutArgsAction); +}; + // Implements the IgnoreResult(action) action. template class IgnoreResultAction { @@ -1053,7 +1103,13 @@ typedef internal::IgnoredValue Unused; template template Action::Action(const Action& from) - : impl_(new internal::ActionAdaptor(from)) {} + : +#if GTEST_LANG_CXX11 + fun_(from.fun_), +#endif + impl_(from.impl_ == NULL ? NULL + : new internal::ActionAdaptor(from)) { +} // Creates an action that returns 'value'. 'value' is passed by value // instead of const reference - otherwise Return("string literal") From 373481c5a9b9bf08c158703d6dc5ab58d4dee0cc Mon Sep 17 00:00:00 2001 From: Gennadiy Civil Date: Wed, 11 Apr 2018 15:46:57 -0400 Subject: [PATCH 2/2] ...merging --- googlemock/src/gmock-internal-utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/googlemock/src/gmock-internal-utils.cc b/googlemock/src/gmock-internal-utils.cc index 20c5a8db..3fca3f26 100644 --- a/googlemock/src/gmock-internal-utils.cc +++ b/googlemock/src/gmock-internal-utils.cc @@ -188,7 +188,7 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message, std::cout << ::std::flush; } -void IllegalDoDefault(const char* file, int line) { +GTEST_API_ void IllegalDoDefault(const char* file, int line) { internal::Assert( false, file, line, "You are using DoDefault() inside a composite action like "