Googletest export

Support templating MockFunction over function objects besides std::function.

PiperOrigin-RevId: 373586967
diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h
index f1bd79c..41323c1 100644
--- a/googlemock/include/gmock/gmock-spec-builders.h
+++ b/googlemock/include/gmock/gmock-spec-builders.h
@@ -1838,12 +1838,12 @@
 It makes use of MockFunction easier by allowing it to accept more F arguments
 than just function signatures.
 
-Specializations provided here cover only a signature type itself and
-std::function. However, if need be it can be easily extended to cover also other
-types (like for example boost::function).
+Specializations provided here cover a signature type itself and any template
+that can be parameterized with a signature, including std::function and
+boost::function.
 */
 
-template <typename F>
+template <typename F, typename = void>
 struct SignatureOf;
 
 template <typename R, typename... Args>
@@ -1851,8 +1851,10 @@
   using type = R(Args...);
 };
 
-template <typename F>
-struct SignatureOf<std::function<F>> : SignatureOf<F> {};
+template <template <typename> class C, typename F>
+struct SignatureOf<C<F>,
+                   typename std::enable_if<std::is_function<F>::value>::type>
+    : SignatureOf<F> {};
 
 template <typename F>
 using SignatureOfT = typename SignatureOf<F>::type;
diff --git a/googlemock/test/gmock-function-mocker_test.cc b/googlemock/test/gmock-function-mocker_test.cc
index 45a524e..cf76fa9 100644
--- a/googlemock/test/gmock-function-mocker_test.cc
+++ b/googlemock/test/gmock-function-mocker_test.cc
@@ -849,7 +849,7 @@
 
 template <typename Expected, typename F>
 static constexpr bool IsMockFunctionTemplateArgumentDeducedTo(
-    const MockFunction<F>&) {
+    const internal::MockFunction<F>&) {
   return std::is_same<F, Expected>::value;
 }
 
@@ -868,14 +868,14 @@
            IsMockFunctionTemplateArgumentDeducedForRawSignature) {
   using Argument = TypeParam;
   MockFunction<Argument> foo;
-  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<Argument>(foo));
+  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
 }
 
 TYPED_TEST(MockMethodMockFunctionSignatureTest,
            IsMockFunctionTemplateArgumentDeducedForStdFunction) {
   using Argument = std::function<TypeParam>;
   MockFunction<Argument> foo;
-  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<Argument>(foo));
+  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
 }
 
 TYPED_TEST(
@@ -887,15 +887,27 @@
   EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
 }
 
+template <typename F>
+struct AlternateCallable {
+};
+
+TYPED_TEST(MockMethodMockFunctionSignatureTest,
+           IsMockFunctionTemplateArgumentDeducedForAlternateCallable) {
+  using Argument = AlternateCallable<TypeParam>;
+  MockFunction<Argument> foo;
+  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
+}
+
 TYPED_TEST(
     MockMethodMockFunctionSignatureTest,
-    IsMockFunctionAsStdFunctionMethodSignatureTheSameForRawSignatureAndStdFunction) {
-  using ForRawSignature = decltype(&MockFunction<TypeParam>::AsStdFunction);
+    IsMockFunctionCallMethodSignatureTheSameForAlternateCallable) {
+  using ForRawSignature = decltype(&MockFunction<TypeParam>::Call);
   using ForStdFunction =
-      decltype(&MockFunction<std::function<TypeParam>>::AsStdFunction);
+      decltype(&MockFunction<std::function<TypeParam>>::Call);
   EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
 }
 
+
 struct MockMethodSizes0 {
   MOCK_METHOD(void, func, ());
 };