diff --git a/googlemock/include/gmock/gmock-generated-nice-strict.h.pump b/googlemock/include/gmock/gmock-generated-nice-strict.h.pump index 3ee1ce7f..4973c356 100644 --- a/googlemock/include/gmock/gmock-generated-nice-strict.h.pump +++ b/googlemock/include/gmock/gmock-generated-nice-strict.h.pump @@ -52,10 +52,9 @@ $var n = 10 $$ The maximum arity we support. // NiceMock. // // NiceMock, NaggyMock, and StrictMock "inherit" the constructors of -// their respective base class, with up-to $n arguments. Therefore -// you can write NiceMock(5, "a") to construct a nice mock -// where MockFoo has a constructor that accepts (int, const char*), -// for example. +// their respective base class. Therefore you can write +// NiceMock(5, "a") to construct a nice mock where MockFoo +// has a constructor that accepts (int, const char*), for example. // // A known limitation is that NiceMock, NaggyMock, // and StrictMock only works for mock methods defined using @@ -64,10 +63,6 @@ $var n = 10 $$ The maximum arity we support. // or "strict" modifier may not affect it, depending on the compiler. // In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT // supported. -// -// Another known limitation is that the constructors of the base mock -// cannot have arguments passed by non-const reference, which are -// banned by the Google C++ style guide anyway. #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ @@ -88,44 +83,79 @@ $var method=[[$if kind==0 [[AllowUninterestingCalls]] $elif kind==1 [[WarnUninterestingCalls]] $else [[FailUninterestingCalls]]]] -template -class $clazz : public MockClass { - public: - // We don't factor out the constructor body to a common method, as - // we have to avoid a possible clash with members of MockClass. - $clazz() { - ::testing::Mock::$method( - internal::ImplicitCast_(this)); - } +namespace internal { - // C++ doesn't (yet) allow inheritance of constructors, so we have - // to define it for each arity. +// $clazz[[]]Base serves as a mix-in to establish the "uninteresting call" +// behavior for $clazz on construction. It accomplishes this via CRTP to get +// access to the derived MockClass. +template +class $clazz[[]]Base { + protected: + $clazz[[]]Base(); + + ~$clazz[[]]Base(); +}; + +} // namespace internal + +template +class $clazz : public MockClass, public internal::$clazz[[]]Base { + public: + $clazz() : MockClass() {} + +#if GTEST_LANG_CXX11 + // Ideally, we would inherit base class's constructors through a using + // declaration, which would preserve their visibility. However, many existing + // tests rely on the fact that current implementation reexports protected + // constructors as public. These tests would need to be cleaned up first. + + // Single argument constructor is special-cased so that it can be + // made explicit. + template + explicit $clazz(A&& arg) : MockClass(std::forward(arg)) {} + + template + $clazz(A1&& arg1, A2&& arg2, An&&... args) + : MockClass(std::forward(arg1), std::forward(arg2), + std::forward(args)...) {} +#else + // C++98 doesn't have variadic templates, so we have to define one + // for each arity. template - explicit $clazz(const A1& a1) : MockClass(a1) { - ::testing::Mock::$method( - internal::ImplicitCast_(this)); - } + explicit $clazz(const A1& a1) : MockClass(a1) {} $range i 2..n $for i [[ $range j 1..i template <$for j, [[typename A$j]]> - $clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) { - ::testing::Mock::$method( - internal::ImplicitCast_(this)); - } + $clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) {} ]] - virtual ~$clazz() { - ::testing::Mock::UnregisterCallReaction( - internal::ImplicitCast_(this)); - } +#endif // GTEST_LANG_CXX11 private: GTEST_DISALLOW_COPY_AND_ASSIGN_($clazz); }; +namespace internal { + +template +$clazz[[]]Base::$clazz[[]]Base() { + ::testing::Mock::$method( + internal::ImplicitCast_( + static_cast<$clazz *>(this))); +} + +template +$clazz[[]]Base::~$clazz[[]]Base() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_( + static_cast<$clazz*>(this))); +} + +} // namespace internal + ]] // The following specializations catch some (relatively more common)