aboutsummaryrefslogtreecommitdiffstats
path: root/googlemock
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2018-12-19 03:16:02 -0500
committerMark Barolak <mbar@google.com>2018-12-20 14:09:39 -0500
commit9494c45e75a55547f3f183a1161fbd39d29b994e (patch)
treebb2ad87a1942c67306b6c0cfc7eae4e01221801f /googlemock
parente26a3fa13ca21500773293946e92ec72f8d8c9ea (diff)
downloadgoogletest-9494c45e75a55547f3f183a1161fbd39d29b994e.tar.gz
googletest-9494c45e75a55547f3f183a1161fbd39d29b994e.tar.bz2
googletest-9494c45e75a55547f3f183a1161fbd39d29b994e.zip
Googletest export
Use std::function to implement type erasure in Action, wrapping the legacy ActionInterface if necessary. This makes functors / std::function the primary way to implement Action; the existing ActionInterface implementations are handled through ActionAdaptor. The existing actions are not (yet) migrated though; they'll pay the cost of one additional indirection - but that should be negligible. PiperOrigin-RevId: 226126137
Diffstat (limited to 'googlemock')
-rw-r--r--googlemock/include/gmock/gmock-actions.h76
1 files changed, 20 insertions, 56 deletions
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h
index 4fd3400f..8b3c03b0 100644
--- a/googlemock/include/gmock/gmock-actions.h
+++ b/googlemock/include/gmock/gmock-actions.h
@@ -69,9 +69,6 @@ namespace testing {
namespace internal {
-template <typename F1, typename F2>
-class ActionAdaptor;
-
// BuiltInDefaultValueGetter<T, true>::Get() returns a
// default-constructed T value. BuiltInDefaultValueGetter<T,
// false>::Get() crashes with an error.
@@ -342,6 +339,19 @@ class ActionInterface {
// object as a handle to it.
template <typename F>
class Action {
+ // Adapter class to allow constructing Action from a legacy ActionInterface.
+ // New code should create Actions from functors instead.
+ struct ActionAdapter {
+ // Adapter must be copyable to satisfy std::function requirements.
+ ::std::shared_ptr<ActionInterface<F>> impl_;
+
+ template <typename... Args>
+ typename internal::Function<F>::Result operator()(Args&&... args) {
+ return impl_->Perform(
+ ::std::forward_as_tuple(::std::forward<Args>(args)...));
+ }
+ };
+
public:
typedef typename internal::Function<F>::Result Result;
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
@@ -359,19 +369,17 @@ class Action {
Action(G&& fun) : fun_(::std::forward<G>(fun)) {} // NOLINT
// Constructs an Action from its implementation.
- explicit Action(ActionInterface<F>* impl) : impl_(impl) {}
+ explicit Action(ActionInterface<F>* impl)
+ : fun_(ActionAdapter{::std::shared_ptr<ActionInterface<F>>(impl)}) {}
// This constructor allows us to turn an Action<Func> object into an
// Action<F>, as long as F's arguments can be implicitly converted
- // to Func's and Func's return type can be implicitly converted to
- // F's.
+ // to Func's and Func's return type can be implicitly converted to F's.
template <typename Func>
- explicit Action(const Action<Func>& action);
+ explicit Action(const Action<Func>& action) : fun_(action.fun_) {}
// Returns true iff this is the DoDefault() action.
- bool IsDoDefault() const {
- return impl_ == nullptr && fun_ == nullptr;
- }
+ bool IsDoDefault() const { return fun_ == nullptr; }
// Performs the action. Note that this method is const even though
// the corresponding method in ActionInterface is not. The reason
@@ -383,25 +391,15 @@ class Action {
if (IsDoDefault()) {
internal::IllegalDoDefault(__FILE__, __LINE__);
}
- if (fun_ != nullptr) {
- return internal::Apply(fun_, ::std::move(args));
- }
- return impl_->Perform(args);
+ return internal::Apply(fun_, ::std::move(args));
}
private:
- template <typename F1, typename F2>
- friend class internal::ActionAdaptor;
-
template <typename G>
friend class Action;
- // Action can be implemented either as a generic functor (via std::function),
- // or legacy ActionInterface. The invariant is that at most one of fun_ and
- // impl_ may be nonnull; both are null iff this is the default action.
- // FIXME: Fold the ActionInterface into std::function.
+ // fun_ is an empty function iff this is the DoDefault() action.
::std::function<F> fun_;
- ::std::shared_ptr<ActionInterface<F>> impl_;
};
// The PolymorphicAction class template makes it easy to implement a
@@ -480,26 +478,6 @@ inline PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl) {
namespace internal {
-// Allows an Action<F2> object to pose as an Action<F1>, as long as F2
-// and F1 are compatible.
-template <typename F1, typename F2>
-class ActionAdaptor : public ActionInterface<F1> {
- public:
- typedef typename internal::Function<F1>::Result Result;
- typedef typename internal::Function<F1>::ArgumentTuple ArgumentTuple;
-
- explicit ActionAdaptor(const Action<F2>& from) : impl_(from.impl_) {}
-
- Result Perform(const ArgumentTuple& args) override {
- return impl_->Perform(args);
- }
-
- private:
- const std::shared_ptr<ActionInterface<F2>> impl_;
-
- GTEST_DISALLOW_ASSIGN_(ActionAdaptor);
-};
-
// Helper struct to specialize ReturnAction to execute a move instead of a copy
// on return. Useful for move-only types, but could be used on any type.
template <typename T>
@@ -1066,20 +1044,6 @@ struct DoAllAction {
// EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
typedef internal::IgnoredValue Unused;
-// This constructor allows us to turn an Action<From> object into an
-// Action<To>, as long as To's arguments can be implicitly converted
-// to From's and From's return type cann be implicitly converted to
-// To's.
-template <typename To>
-template <typename From>
-Action<To>::Action(const Action<From>& from)
- :
- fun_(from.fun_),
- impl_(from.impl_ == nullptr
- ? nullptr
- : new internal::ActionAdaptor<To, From>(from)) {
-}
-
// Creates an action that does actions a1, a2, ..., sequentially in
// each invocation.
template <typename... Action>