Googletest export

Change string matchers, like HasSubstr, to accept `string_view` input if available.

PiperOrigin-RevId: 315726484
diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h
index 08fd6d1..0bc9b36 100644
--- a/googlemock/include/gmock/gmock-matchers.h
+++ b/googlemock/include/gmock/gmock-matchers.h
@@ -903,9 +903,10 @@
 template <typename StringType>
 class StrEqualityMatcher {
  public:
-  StrEqualityMatcher(const StringType& str, bool expect_eq,
-                     bool case_sensitive)
-      : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {}
+  StrEqualityMatcher(StringType str, bool expect_eq, bool case_sensitive)
+      : string_(std::move(str)),
+        expect_eq_(expect_eq),
+        case_sensitive_(case_sensitive) {}
 
 #if GTEST_INTERNAL_HAS_STRING_VIEW
   bool MatchAndExplain(const internal::StringView& s,
@@ -3990,52 +3991,60 @@
 // String matchers.
 
 // Matches a string equal to str.
-inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrEq(
-    const std::string& str) {
+template <typename T = std::string>
+PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrEq(
+    const internal::StringLike<T>& str) {
   return MakePolymorphicMatcher(
-      internal::StrEqualityMatcher<std::string>(str, true, true));
+      internal::StrEqualityMatcher<std::string>(std::string(str), true, true));
 }
 
 // Matches a string not equal to str.
-inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrNe(
-    const std::string& str) {
+template <typename T = std::string>
+PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrNe(
+    const internal::StringLike<T>& str) {
   return MakePolymorphicMatcher(
-      internal::StrEqualityMatcher<std::string>(str, false, true));
+      internal::StrEqualityMatcher<std::string>(std::string(str), false, true));
 }
 
 // Matches a string equal to str, ignoring case.
-inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseEq(
-    const std::string& str) {
+template <typename T = std::string>
+PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseEq(
+    const internal::StringLike<T>& str) {
   return MakePolymorphicMatcher(
-      internal::StrEqualityMatcher<std::string>(str, true, false));
+      internal::StrEqualityMatcher<std::string>(std::string(str), true, false));
 }
 
 // Matches a string not equal to str, ignoring case.
-inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseNe(
-    const std::string& str) {
-  return MakePolymorphicMatcher(
-      internal::StrEqualityMatcher<std::string>(str, false, false));
+template <typename T = std::string>
+PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseNe(
+    const internal::StringLike<T>& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<std::string>(
+      std::string(str), false, false));
 }
 
 // Creates a matcher that matches any string, std::string, or C string
 // that contains the given substring.
-inline PolymorphicMatcher<internal::HasSubstrMatcher<std::string> > HasSubstr(
-    const std::string& substring) {
+template <typename T = std::string>
+PolymorphicMatcher<internal::HasSubstrMatcher<std::string> > HasSubstr(
+    const internal::StringLike<T>& substring) {
   return MakePolymorphicMatcher(
-      internal::HasSubstrMatcher<std::string>(substring));
+      internal::HasSubstrMatcher<std::string>(std::string(substring)));
 }
 
 // Matches a string that starts with 'prefix' (case-sensitive).
-inline PolymorphicMatcher<internal::StartsWithMatcher<std::string> > StartsWith(
-    const std::string& prefix) {
+template <typename T = std::string>
+PolymorphicMatcher<internal::StartsWithMatcher<std::string> > StartsWith(
+    const internal::StringLike<T>& prefix) {
   return MakePolymorphicMatcher(
-      internal::StartsWithMatcher<std::string>(prefix));
+      internal::StartsWithMatcher<std::string>(std::string(prefix)));
 }
 
 // Matches a string that ends with 'suffix' (case-sensitive).
-inline PolymorphicMatcher<internal::EndsWithMatcher<std::string> > EndsWith(
-    const std::string& suffix) {
-  return MakePolymorphicMatcher(internal::EndsWithMatcher<std::string>(suffix));
+template <typename T = std::string>
+PolymorphicMatcher<internal::EndsWithMatcher<std::string> > EndsWith(
+    const internal::StringLike<T>& suffix) {
+  return MakePolymorphicMatcher(
+      internal::EndsWithMatcher<std::string>(std::string(suffix)));
 }
 
 #if GTEST_HAS_STD_WSTRING
diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc
index 5db0a7a..a22ff34 100644
--- a/googlemock/test/gmock-matchers_test.cc
+++ b/googlemock/test/gmock-matchers_test.cc
@@ -1226,6 +1226,25 @@
 
 // Tests string comparison matchers.
 
+template <typename T = std::string>
+std::string FromStringLike(internal::StringLike<T> str) {
+  return std::string(str);
+}
+
+TEST(StringLike, TestConversions) {
+  EXPECT_EQ("foo", FromStringLike("foo"));
+  EXPECT_EQ("foo", FromStringLike(std::string("foo")));
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  EXPECT_EQ("foo", FromStringLike(internal::StringView("foo")));
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+  // Non deducible types.
+  EXPECT_EQ("", FromStringLike({}));
+  EXPECT_EQ("foo", FromStringLike({'f', 'o', 'o'}));
+  const char buf[] = "foo";
+  EXPECT_EQ("foo", FromStringLike({buf, buf + 3}));
+}
+
 TEST(StrEqTest, MatchesEqualString) {
   Matcher<const char*> m = StrEq(std::string("Hello"));
   EXPECT_TRUE(m.Matches("Hello"));
@@ -1237,7 +1256,8 @@
   EXPECT_FALSE(m2.Matches("Hi"));
 
 #if GTEST_INTERNAL_HAS_STRING_VIEW
-  Matcher<const internal::StringView&> m3 = StrEq("Hello");
+  Matcher<const internal::StringView&> m3 =
+      StrEq(internal::StringView("Hello"));
   EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
   EXPECT_FALSE(m3.Matches(internal::StringView("hello")));
   EXPECT_FALSE(m3.Matches(internal::StringView()));
@@ -1274,7 +1294,7 @@
   EXPECT_FALSE(m2.Matches("Hello"));
 
 #if GTEST_INTERNAL_HAS_STRING_VIEW
-  Matcher<const internal::StringView> m3 = StrNe("Hello");
+  Matcher<const internal::StringView> m3 = StrNe(internal::StringView("Hello"));
   EXPECT_TRUE(m3.Matches(internal::StringView("")));
   EXPECT_TRUE(m3.Matches(internal::StringView()));
   EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
@@ -1298,7 +1318,8 @@
   EXPECT_FALSE(m2.Matches("Hi"));
 
 #if GTEST_INTERNAL_HAS_STRING_VIEW
-  Matcher<const internal::StringView&> m3 = StrCaseEq(std::string("Hello"));
+  Matcher<const internal::StringView&> m3 =
+      StrCaseEq(internal::StringView("Hello"));
   EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
   EXPECT_TRUE(m3.Matches(internal::StringView("hello")));
   EXPECT_FALSE(m3.Matches(internal::StringView("Hi")));
@@ -1348,7 +1369,8 @@
   EXPECT_FALSE(m2.Matches("Hello"));
 
 #if GTEST_INTERNAL_HAS_STRING_VIEW
-  Matcher<const internal::StringView> m3 = StrCaseNe("Hello");
+  Matcher<const internal::StringView> m3 =
+      StrCaseNe(internal::StringView("Hello"));
   EXPECT_TRUE(m3.Matches(internal::StringView("Hi")));
   EXPECT_TRUE(m3.Matches(internal::StringView()));
   EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
@@ -1397,7 +1419,8 @@
 #if GTEST_INTERNAL_HAS_STRING_VIEW
 // Tests that HasSubstr() works for matching StringView-typed values.
 TEST(HasSubstrTest, WorksForStringViewClasses) {
-  const Matcher<internal::StringView> m1 = HasSubstr("foo");
+  const Matcher<internal::StringView> m1 =
+      HasSubstr(internal::StringView("foo"));
   EXPECT_TRUE(m1.Matches(internal::StringView("I love food.")));
   EXPECT_FALSE(m1.Matches(internal::StringView("tofo")));
   EXPECT_FALSE(m1.Matches(internal::StringView()));
@@ -1650,7 +1673,8 @@
   EXPECT_FALSE(m2.Matches(" Hi"));
 
 #if GTEST_INTERNAL_HAS_STRING_VIEW
-  const Matcher<internal::StringView> m_empty = StartsWith("");
+  const Matcher<internal::StringView> m_empty =
+      StartsWith(internal::StringView(""));
   EXPECT_TRUE(m_empty.Matches(internal::StringView()));
   EXPECT_TRUE(m_empty.Matches(internal::StringView("")));
   EXPECT_TRUE(m_empty.Matches(internal::StringView("not empty")));
@@ -1678,7 +1702,8 @@
   EXPECT_FALSE(m2.Matches("Hi "));
 
 #if GTEST_INTERNAL_HAS_STRING_VIEW
-  const Matcher<const internal::StringView&> m4 = EndsWith("");
+  const Matcher<const internal::StringView&> m4 =
+      EndsWith(internal::StringView(""));
   EXPECT_TRUE(m4.Matches("Hi"));
   EXPECT_TRUE(m4.Matches(""));
   EXPECT_TRUE(m4.Matches(internal::StringView()));
@@ -1710,7 +1735,8 @@
   EXPECT_TRUE(m3.Matches(internal::StringView("abcz")));
   EXPECT_FALSE(m3.Matches(internal::StringView("1az")));
   EXPECT_FALSE(m3.Matches(internal::StringView()));
-  const Matcher<const internal::StringView&> m4 = MatchesRegex("");
+  const Matcher<const internal::StringView&> m4 =
+      MatchesRegex(internal::StringView(""));
   EXPECT_TRUE(m4.Matches(internal::StringView("")));
   EXPECT_TRUE(m4.Matches(internal::StringView()));
 #endif  // GTEST_INTERNAL_HAS_STRING_VIEW
@@ -1749,7 +1775,8 @@
   EXPECT_TRUE(m3.Matches(internal::StringView("az1")));
   EXPECT_FALSE(m3.Matches(internal::StringView("1a")));
   EXPECT_FALSE(m3.Matches(internal::StringView()));
-  const Matcher<const internal::StringView&> m4 = ContainsRegex("");
+  const Matcher<const internal::StringView&> m4 =
+      ContainsRegex(internal::StringView(""));
   EXPECT_TRUE(m4.Matches(internal::StringView("")));
   EXPECT_TRUE(m4.Matches(internal::StringView()));
 #endif  // GTEST_INTERNAL_HAS_STRING_VIEW
diff --git a/googletest/include/gtest/gtest-matchers.h b/googletest/include/gtest/gtest-matchers.h
index a61cef4..04cc63d 100644
--- a/googletest/include/gtest/gtest-matchers.h
+++ b/googletest/include/gtest/gtest-matchers.h
@@ -612,6 +612,10 @@
   static const char* NegatedDesc() { return "isn't >="; }
 };
 
+template <typename T, typename = typename std::enable_if<
+                          std::is_constructible<std::string, T>::value>::type>
+using StringLike = T;
+
 // Implements polymorphic matchers MatchesRegex(regex) and
 // ContainsRegex(regex), which can be used as a Matcher<T> as long as
 // T can be converted to a string.
@@ -672,9 +676,10 @@
     const internal::RE* regex) {
   return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
 }
-inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
-    const std::string& regex) {
-  return MatchesRegex(new internal::RE(regex));
+template <typename T = std::string>
+PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::StringLike<T>& regex) {
+  return MatchesRegex(new internal::RE(std::string(regex)));
 }
 
 // Matches a string that contains regular expression 'regex'.
@@ -683,9 +688,10 @@
     const internal::RE* regex) {
   return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
 }
-inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
-    const std::string& regex) {
-  return ContainsRegex(new internal::RE(regex));
+template <typename T = std::string>
+PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::StringLike<T>& regex) {
+  return ContainsRegex(new internal::RE(std::string(regex)));
 }
 
 // Creates a polymorphic matcher that matches anything equal to x.