diff options
author | Aaron Jacobs <jacobsa@google.com> | 2022-05-12 02:00:34 (GMT) |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-05-12 02:01:15 (GMT) |
commit | cbca6bc3957b28b8062f20b65f9349d94a4bf0b3 (patch) | |
tree | e51133bf307266ec17ce6d051fbc61b75db2e157 /googlemock/include | |
parent | 5e6a533680fc8292c31f31664d80c48440d4a526 (diff) | |
download | googletest-cbca6bc3957b28b8062f20b65f9349d94a4bf0b3.zip googletest-cbca6bc3957b28b8062f20b65f9349d94a4bf0b3.tar.gz googletest-cbca6bc3957b28b8062f20b65f9349d94a4bf0b3.tar.bz2 |
gmock-actions: provide a const reference when converting in ReturnAction.
It doesn't make semantic sense for the conversion to modify the input, and the
fact that it's allowed to do so appears to have just been a historical accident.
PiperOrigin-RevId: 448135555
Change-Id: Id10f17af38cf3947ee25fe10654d97527173ebfc
Diffstat (limited to 'googlemock/include')
-rw-r--r-- | googlemock/include/gmock/gmock-actions.h | 47 |
1 files changed, 15 insertions, 32 deletions
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index 208295f..df2effd 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -322,6 +322,12 @@ 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...>; +// Like std::as_const from C++17. +template <typename T> +typename std::add_const<T>::type& as_const(T& t) { + return t; +} + } // namespace internal // Specialized for function types below. @@ -872,17 +878,14 @@ class ReturnAction final { public: explicit ReturnAction(R value) : value_(std::move(value)) {} - // Support conversion to function types with compatible return types. See the - // documentation on Return for the definition of compatible. - template <typename U, typename... Args> + template <typename U, typename... Args, + typename = typename std::enable_if<conjunction< + // See the requirements documented on Return. + negation<std::is_same<void, U>>, // + negation<std::is_reference<U>>, // + std::is_convertible<const R&, U>, // + std::is_copy_constructible<U>>::value>::type> operator Action<U(Args...)>() const { // NOLINT - // Check our requirements on the return type. - static_assert(!std::is_reference<U>::value, - "use ReturnRef instead of Return to return a reference"); - - static_assert(!std::is_void<U>::value, - "Can't use Return() on an action expected to return `void`."); - return Impl<U>(value_); } @@ -918,27 +921,7 @@ class ReturnAction final { // that does `return R()` requires R to be implicitly convertible to // U, and uses that path for the conversion, even U Result has an // explicit constructor from R. - // - // We provide non-const access to input_value to the conversion - // code. It's not clear whether this makes semantic sense -- what - // would it mean for the conversion to modify the input value? This - // appears to be an accident of history: - // - // 1. Before the first public commit the input value was simply an - // object of type R embedded directly in the Impl object. The - // result value wasn't yet eagerly created, and the Impl class's - // Perform method was const, so the implicit conversion when it - // returned the value was from const R&. - // - // 2. Google changelist 6490411 changed ActionInterface::Perform to - // be non-const, citing the fact that an action can have side - // effects and be stateful. Impl::Perform was updated like all - // other actions, probably without consideration of the fact - // that side effects and statefulness don't make sense for - // Return. From this point on the conversion had non-const - // access to the input value. - // - value(ImplicitCast_<U>(input_value)) {} + value(ImplicitCast_<U>(internal::as_const(input_value))) {} // A copy of the value originally provided by the user. We retain this in // addition to the value of the mock function's result type below in case @@ -1763,7 +1746,7 @@ internal::WithArgsAction<typename std::decay<InnerAction>::type> WithoutArgs( // * U is not void. // * U is not a reference type. (Use ReturnRef instead.) // * U is copy-constructible. -// * R& is convertible to U. +// * const R& is convertible to U. // // The Action<U(Args)...> object contains the R value from which the U return // value is constructed (a copy of the argument to Return). This means that the |