diff options
Diffstat (limited to 'googlemock')
-rw-r--r-- | googlemock/include/gmock/gmock-actions.h | 65 | ||||
-rw-r--r-- | googlemock/include/gmock/gmock-matchers.h | 3 |
2 files changed, 36 insertions, 32 deletions
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index f9fee55..c83a99a 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -322,9 +322,6 @@ struct is_callable_r_impl<void_t<call_result_t<F, Args...>>, R, F, Args...> template <typename R, typename F, typename... Args> using is_callable_r = is_callable_r_impl<void, R, F, Args...>; -template <typename F> -class TypedExpectation; - // Specialized for function types below. template <typename F> class OnceAction; @@ -441,9 +438,6 @@ class OnceAction<Result(Args...)> final { } private: - // Allow TypedExpectation::WillOnce to use our type-unsafe API below. - friend class TypedExpectation<Result(Args...)>; - // An adaptor that wraps a callable that is compatible with our signature and // being invoked as an rvalue reference so that it can be used as an // StdFunctionAdaptor. This throws away type safety, but that's fine because @@ -900,12 +894,12 @@ struct ByMoveWrapper { // of gtl::Container() is passed into Return. // template <typename R> -class ReturnAction { +class ReturnAction final { public: // Constructs a ReturnAction object from the value to be returned. // 'value' is passed by value instead of by const reference in order // to allow Return("string literal") to compile. - explicit ReturnAction(R value) : value_(new R(std::move(value))) {} + explicit ReturnAction(R value) : value_(std::move(value)) {} // This template type conversion operator allows Return(x) to be // used in ANY function that returns x's type. @@ -924,19 +918,19 @@ class ReturnAction { "use ReturnRef instead of Return to return a reference"); static_assert(!std::is_void<Result>::value, "Can't use Return() on an action expected to return `void`."); - return Action<F>(new Impl<R, F>(value_)); + return Action<F>(new Impl<F>(value_)); } private: // Implements the Return(x) action for a particular function type F. - template <typename R_, typename F> + template <typename F> class Impl : public ActionInterface<F> { public: typedef typename Function<F>::Result Result; typedef typename Function<F>::ArgumentTuple ArgumentTuple; - explicit Impl(const std::shared_ptr<R>& value) - : value_before_cast_(*value), + explicit Impl(const R& value) + : value_before_cast_(value), // Make an implicit conversion to Result before initializing the // Result object we store, avoiding calling any explicit constructor // of Result from R. @@ -961,30 +955,39 @@ class ReturnAction { Impl& operator=(const Impl&) = delete; }; - // Partially specialize for ByMoveWrapper. This version of ReturnAction will - // move its contents instead. - template <typename R_, typename F> - class Impl<ByMoveWrapper<R_>, F> : public ActionInterface<F> { - public: - typedef typename Function<F>::Result Result; - typedef typename Function<F>::ArgumentTuple ArgumentTuple; + R value_; +}; - explicit Impl(const std::shared_ptr<R>& wrapper) - : performed_(false), wrapper_(wrapper) {} +// A specialization of ReturnAction<R> when R is ByMoveWrapper<T> for some T. +// +// This version applies the type system-defeating hack of moving from T even in +// the const call operator, checking at runtime that it isn't called more than +// once, since the user has declared their intent to do so by using ByMove. +template <typename T> +class ReturnAction<ByMoveWrapper<T>> final { + public: + explicit ReturnAction(ByMoveWrapper<T> wrapper) + : state_(new State(std::move(wrapper.payload))) {} - Result Perform(const ArgumentTuple&) override { - GTEST_CHECK_(!performed_) - << "A ByMove() action should only be performed once."; - performed_ = true; - return std::move(wrapper_->payload); - } + T operator()() const { + GTEST_CHECK_(!state_->called) + << "A ByMove() action must be performed at most once."; - private: - bool performed_; - const std::shared_ptr<R> wrapper_; + state_->called = true; + return std::move(state_->value); + } + + private: + // We store our state on the heap so that we are copyable as required by + // Action, despite the fact that we are stateful and T may not be copyable. + struct State { + explicit State(T&& value_in) : value(std::move(value_in)) {} + + T value; + bool called = false; }; - const std::shared_ptr<R> value_; + const std::shared_ptr<State> state_; }; // Implements the ReturnNull() action. diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index c349c20..6282901 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -5068,7 +5068,8 @@ inline bool ExplainMatchResult(M matcher, const T& value, // // MATCHER_P(XAndYThat, matcher, // "X that " + DescribeMatcher<int>(matcher, negation) + -// " and Y that " + DescribeMatcher<double>(matcher, negation)) { +// (negation ? " or" : " and") + " Y that " + +// DescribeMatcher<double>(matcher, negation)) { // return ExplainMatchResult(matcher, arg.x(), result_listener) && // ExplainMatchResult(matcher, arg.y(), result_listener); // } |