diff options
author | Aaron Jacobs <jacobsa@google.com> | 2022-04-27 15:48:35 (GMT) |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-04-27 15:49:18 (GMT) |
commit | 830fb567285c63ab5b5873e2e8b02f2249864916 (patch) | |
tree | 6e7af05a8663ae974f3b7daf49bbf111eaefb055 /googlemock | |
parent | c144d78f8295da3dbae3ad2d5fe66a9a42f8ce74 (diff) | |
download | googletest-830fb567285c63ab5b5873e2e8b02f2249864916.zip googletest-830fb567285c63ab5b5873e2e8b02f2249864916.tar.gz googletest-830fb567285c63ab5b5873e2e8b02f2249864916.tar.bz2 |
gmock-actions: improve comments and tests for the implicit cast in Return.
Commit a070cbd91c added an implicit cast to this path but didn't leave a very
clear explanation for why it was desirable, a clear example, or even test
coverage. Add a better comment and a test that fails when the implicit cast is
removed.
PiperOrigin-RevId: 444871311
Change-Id: I127982fa8d5bce9b6d1b68177c12dc0709449164
Diffstat (limited to 'googlemock')
-rw-r--r-- | googlemock/include/gmock/gmock-actions.h | 15 | ||||
-rw-r--r-- | googlemock/test/gmock-actions_test.cc | 31 |
2 files changed, 39 insertions, 7 deletions
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index 5836f17..f9fee55 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -935,15 +935,16 @@ class ReturnAction { typedef typename Function<F>::Result Result; typedef typename Function<F>::ArgumentTuple ArgumentTuple; - // The implicit cast is necessary when Result has more than one - // single-argument constructor (e.g. Result is std::vector<int>) and R - // has a type conversion operator template. In that case, value_(value) - // won't compile as the compiler doesn't known which constructor of - // Result to call. ImplicitCast_ forces the compiler to convert R to - // Result without considering explicit constructors, thus resolving the - // ambiguity. value_ is then initialized using its copy constructor. explicit Impl(const std::shared_ptr<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. + // + // This simulates the language rules: a function with return type + // Result that does `return R()` requires R to be implicitly + // convertible to Result, and uses that path for the conversion, even + // if Result has an explicit constructor from R. value_(ImplicitCast_<Result>(value_before_cast_)) {} Result Perform(const ArgumentTuple&) override { return value_; } diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index a33358a..db112f1 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -667,6 +667,37 @@ TEST(ReturnTest, SupportsWrapperReturnType) { EXPECT_THAT(result, ::testing::ElementsAre(0, 1, 2, 3, 4)); } +TEST(ReturnTest, PrefersConversionOperator) { + // Define types In and Out such that: + // + // * In is implicitly convertible to Out. + // * Out also has an explicit constructor from In. + // + struct In; + struct Out { + int x; + + explicit Out(const int x) : x(x) {} + explicit Out(const In&) : x(0) {} + }; + + struct In { + operator Out() const { return Out{19}; } // NOLINT + }; + + // Assumption check: the C++ language rules are such that a function that + // returns Out which uses In a return statement will use the implicit + // conversion path rather than the explicit constructor. + EXPECT_THAT([]() -> Out { return In(); }(), Field(&Out::x, 19)); + + // Return should work the same way: if the mock function's return type is Out + // and we feed Return an In value, then the Out should be created through the + // implicit conversion path rather than the explicit constructor. + MockFunction<Out()> mock; + EXPECT_CALL(mock, Call).WillOnce(Return(In())); + EXPECT_THAT(mock.AsStdFunction()(), Field(&Out::x, 19)); +} + // Tests that Return(v) is covaraint. struct Base { |