@@ -322,6 +322,12 @@ struct is_callable_r_impl<void_t<call_result_t<F, Args...>>, R, F, Args...>
322322template <typename R, typename F, typename ... Args>
323323using is_callable_r = is_callable_r_impl<void , R, F, Args...>;
324324
325+ // Like std::as_const from C++17.
326+ template <typename T>
327+ typename std::add_const<T>::type& as_const (T& t) {
328+ return t;
329+ }
330+
325331} // namespace internal
326332
327333// Specialized for function types below.
@@ -872,17 +878,14 @@ class ReturnAction final {
872878 public:
873879 explicit ReturnAction (R value) : value_(std::move(value)) {}
874880
875- // Support conversion to function types with compatible return types. See the
876- // documentation on Return for the definition of compatible.
877- template <typename U, typename ... Args>
881+ template <typename U, typename ... Args,
882+ typename = typename std::enable_if<conjunction<
883+ // See the requirements documented on Return.
884+ negation<std::is_same<void , U>>, //
885+ negation<std::is_reference<U>>, //
886+ std::is_convertible<const R&, U>, //
887+ std::is_copy_constructible<U>>::value>::type>
878888 operator Action<U(Args...)>() const { // NOLINT
879- // Check our requirements on the return type.
880- static_assert (!std::is_reference<U>::value,
881- " use ReturnRef instead of Return to return a reference" );
882-
883- static_assert (!std::is_void<U>::value,
884- " Can't use Return() on an action expected to return `void`." );
885-
886889 return Impl<U>(value_);
887890 }
888891
@@ -918,27 +921,7 @@ class ReturnAction final {
918921 // that does `return R()` requires R to be implicitly convertible to
919922 // U, and uses that path for the conversion, even U Result has an
920923 // explicit constructor from R.
921- //
922- // We provide non-const access to input_value to the conversion
923- // code. It's not clear whether this makes semantic sense -- what
924- // would it mean for the conversion to modify the input value? This
925- // appears to be an accident of history:
926- //
927- // 1. Before the first public commit the input value was simply an
928- // object of type R embedded directly in the Impl object. The
929- // result value wasn't yet eagerly created, and the Impl class's
930- // Perform method was const, so the implicit conversion when it
931- // returned the value was from const R&.
932- //
933- // 2. Google changelist 6490411 changed ActionInterface::Perform to
934- // be non-const, citing the fact that an action can have side
935- // effects and be stateful. Impl::Perform was updated like all
936- // other actions, probably without consideration of the fact
937- // that side effects and statefulness don't make sense for
938- // Return. From this point on the conversion had non-const
939- // access to the input value.
940- //
941- value(ImplicitCast_<U>(input_value)) {}
924+ value(ImplicitCast_<U>(internal::as_const(input_value))) {}
942925
943926 // A copy of the value originally provided by the user. We retain this in
944927 // 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(
17631746// * U is not void.
17641747// * U is not a reference type. (Use ReturnRef instead.)
17651748// * U is copy-constructible.
1766- // * R& is convertible to U.
1749+ // * const R& is convertible to U.
17671750//
17681751// The Action<U(Args)...> object contains the R value from which the U return
17691752// value is constructed (a copy of the argument to Return). This means that the
0 commit comments