Undo make string matchers work with std::wstring_view due to internal breakages

Reopens: #4912
PiperOrigin-RevId: 953470061
Change-Id: Ie979aa352f0ecbfb27dec5a41aae4b668cf7541b
This commit is contained in:
Abseil Team 2026-07-24 11:26:48 -07:00 committed by Copybara-Service
parent 679a61d3a8
commit 425811f10e
3 changed files with 95 additions and 77 deletions

View File

@ -4982,68 +4982,116 @@ internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
// Matches a string equal to str. // Matches a string equal to str.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StrEqualityMatcher<internal::StringType<T>>> StrEq( PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrEq(
const T& str) { const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<internal::StringType<T>>( internal::StrEqualityMatcher<std::string>(std::string(str), true, true));
internal::StringType<T>(str), true, true));
} }
// Matches a string not equal to str. // Matches a string not equal to str.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StrEqualityMatcher<internal::StringType<T>>> StrNe( PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrNe(
const T& str) { const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<internal::StringType<T>>( internal::StrEqualityMatcher<std::string>(std::string(str), false, true));
internal::StringType<T>(str), false, true));
} }
// Matches a string equal to str, ignoring case. // Matches a string equal to str, ignoring case.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StrEqualityMatcher<internal::StringType<T>>> PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrCaseEq(
StrCaseEq(const T& str) { const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<internal::StringType<T>>( internal::StrEqualityMatcher<std::string>(std::string(str), true, false));
internal::StringType<T>(str), true, false));
} }
// Matches a string not equal to str, ignoring case. // Matches a string not equal to str, ignoring case.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StrEqualityMatcher<internal::StringType<T>>> PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrCaseNe(
StrCaseNe(const T& str) { const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(internal::StrEqualityMatcher<std::string>(
internal::StrEqualityMatcher<internal::StringType<T>>( std::string(str), false, false));
internal::StringType<T>(str), false, false));
} }
// Creates a matcher that matches any string, std::string, or C string // Creates a matcher that matches any string, std::string, or C string
// that contains the given substring. // that contains the given substring.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::HasSubstrMatcher<internal::StringType<T>>> PolymorphicMatcher<internal::HasSubstrMatcher<std::string>> HasSubstr(
HasSubstr(const T& substring) { const internal::StringLike<T>& substring) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::HasSubstrMatcher<internal::StringType<T>>( internal::HasSubstrMatcher<std::string>(std::string(substring)));
internal::StringType<T>(substring)));
} }
// Matches a string that starts with 'prefix' (case-sensitive). // Matches a string that starts with 'prefix' (case-sensitive).
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StartsWithMatcher<internal::StringType<T>>> PolymorphicMatcher<internal::StartsWithMatcher<std::string>> StartsWith(
StartsWith(const T& prefix) { const internal::StringLike<T>& prefix) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StartsWithMatcher<internal::StringType<T>>( internal::StartsWithMatcher<std::string>(std::string(prefix)));
internal::StringType<T>(prefix)));
} }
// Matches a string that ends with 'suffix' (case-sensitive). // Matches a string that ends with 'suffix' (case-sensitive).
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::EndsWithMatcher<internal::StringType<T>>> EndsWith( PolymorphicMatcher<internal::EndsWithMatcher<std::string>> EndsWith(
const T& suffix) { const internal::StringLike<T>& suffix) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::EndsWithMatcher<internal::StringType<T>>( internal::EndsWithMatcher<std::string>(std::string(suffix)));
internal::StringType<T>(suffix)));
} }
#if GTEST_HAS_STD_WSTRING
// Wide string matchers.
// Matches a string equal to str.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrEq(
const std::wstring& str) {
return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::wstring>(str, true, true));
}
// Matches a string not equal to str.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrNe(
const std::wstring& str) {
return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::wstring>(str, false, true));
}
// Matches a string equal to str, ignoring case.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrCaseEq(
const std::wstring& str) {
return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::wstring>(str, true, false));
}
// Matches a string not equal to str, ignoring case.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrCaseNe(
const std::wstring& str) {
return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::wstring>(str, false, false));
}
// Creates a matcher that matches any ::wstring, std::wstring, or C wide string
// that contains the given substring.
inline PolymorphicMatcher<internal::HasSubstrMatcher<std::wstring>> HasSubstr(
const std::wstring& substring) {
return MakePolymorphicMatcher(
internal::HasSubstrMatcher<std::wstring>(substring));
}
// Matches a string that starts with 'prefix' (case-sensitive).
inline PolymorphicMatcher<internal::StartsWithMatcher<std::wstring>> StartsWith(
const std::wstring& prefix) {
return MakePolymorphicMatcher(
internal::StartsWithMatcher<std::wstring>(prefix));
}
// Matches a string that ends with 'suffix' (case-sensitive).
inline PolymorphicMatcher<internal::EndsWithMatcher<std::wstring>> EndsWith(
const std::wstring& suffix) {
return MakePolymorphicMatcher(
internal::EndsWithMatcher<std::wstring>(suffix));
}
#endif // GTEST_HAS_STD_WSTRING
// Creates a polymorphic matcher that matches a 2-tuple where the // Creates a polymorphic matcher that matches a 2-tuple where the
// first field == the second field. // first field == the second field.
inline internal::Eq2Matcher Eq() { return internal::Eq2Matcher(); } inline internal::Eq2Matcher Eq() { return internal::Eq2Matcher(); }

View File

@ -1254,22 +1254,22 @@ TEST(RefTest, ExplainsResult) {
// Tests string comparison matchers. // Tests string comparison matchers.
template <typename T = std::string> template <typename T = std::string>
internal::StringType<T> ToString(T str) { std::string FromStringLike(internal::StringLike<T> str) {
return internal::StringType<T>(str); return std::string(str);
} }
TEST(StringType, TestConversions) { TEST(StringLike, TestConversions) {
EXPECT_EQ("foo", ToString("foo")); EXPECT_EQ("foo", FromStringLike("foo"));
EXPECT_EQ("foo", ToString(std::string("foo"))); EXPECT_EQ("foo", FromStringLike(std::string("foo")));
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
EXPECT_EQ("foo", ToString(internal::StringView("foo"))); EXPECT_EQ("foo", FromStringLike(internal::StringView("foo")));
#endif // GTEST_INTERNAL_HAS_STRING_VIEW #endif // GTEST_INTERNAL_HAS_STRING_VIEW
// Non deducible types. // Non deducible types.
EXPECT_EQ("", ToString({})); EXPECT_EQ("", FromStringLike({}));
EXPECT_EQ("foo", ToString({'f', 'o', 'o'})); EXPECT_EQ("foo", FromStringLike({'f', 'o', 'o'}));
const char buf[] = "foo"; const char buf[] = "foo";
EXPECT_EQ("foo", ToString({buf, buf + 3})); EXPECT_EQ("foo", FromStringLike({buf, buf + 3}));
} }
TEST(StrEqTest, MatchesEqualString) { TEST(StrEqTest, MatchesEqualString) {

View File

@ -45,7 +45,6 @@
#include <memory> #include <memory>
#include <ostream> #include <ostream>
#include <string> #include <string>
#include <string_view>
#include <type_traits> #include <type_traits>
#include "gtest/gtest-printers.h" #include "gtest/gtest-printers.h"
@ -813,36 +812,9 @@ class [[nodiscard]] ImplicitCastEqMatcher {
StoredRhs stored_rhs_; StoredRhs stored_rhs_;
}; };
// Dummy function (never defined) whose return type evaluates to std::string if template <typename T,
// the given type is a string-like type that can be converted to std::string, typename = std::enable_if_t<std::is_constructible_v<std::string, T>>>
// either directly or through an intermediate std::string_view. using StringLike = T;
template <class T>
extern std::enable_if_t<std::is_convertible_v<T, std::string> ||
(std::is_constructible_v<std::string, T> &&
std::is_convertible_v<T, internal::StringView>),
std::string>
ResolveAsString(const void* /* preferred */);
#if GTEST_HAS_STD_WSTRING
// Same as above, but for std::wstring. In cases where both conversions are
// possible, this overload takes lower priority.
template <class T>
extern std::enable_if_t<std::is_convertible_v<T, std::wstring> ||
(std::is_constructible_v<std::wstring, T> &&
std::is_convertible_v<T, std::wstring_view>),
std::wstring>
ResolveAsString(... /* fallback */);
#endif
// Evaluates to the std::basic_string type that the given string-like type can
// be converted to. Prefers std::string over std::wstring if both are possible.
// Fails in a SFINAE-friendly way if no conversion was viable.
//
// For example, const char* and std::string_view would both evaluate to
// std::string, but std::allocator<char> would fail to evaluate via SFINAE
// (despite std::string being constructible from it).
template <typename T>
using StringType = decltype(ResolveAsString<T>(nullptr));
// Implements polymorphic matchers MatchesRegex(regex) and // Implements polymorphic matchers MatchesRegex(regex) and
// ContainsRegex(regex), which can be used as a Matcher<T> as long as // ContainsRegex(regex), which can be used as a Matcher<T> as long as
@ -905,10 +877,9 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true)); return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
} }
template <typename T = std::string> template <typename T = std::string>
std::enable_if_t<std::is_constructible_v<internal::RE, internal::StringType<T>>, PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
PolymorphicMatcher<internal::MatchesRegexMatcher>> const internal::StringLike<T>& regex) {
MatchesRegex(const T& regex) { return MatchesRegex(new internal::RE(std::string(regex)));
return MatchesRegex(new internal::RE(internal::StringType<T>(regex)));
} }
// Matches a string that contains regular expression 'regex'. // Matches a string that contains regular expression 'regex'.
@ -918,10 +889,9 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false)); return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
} }
template <typename T = std::string> template <typename T = std::string>
std::enable_if_t<std::is_constructible_v<internal::RE, internal::StringType<T>>, PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
PolymorphicMatcher<internal::MatchesRegexMatcher>> const internal::StringLike<T>& regex) {
ContainsRegex(const T& regex) { return ContainsRegex(new internal::RE(std::string(regex)));
return ContainsRegex(new internal::RE(internal::StringType<T>(regex)));
} }
// Creates a polymorphic matcher that matches anything equal to x. // Creates a polymorphic matcher that matches anything equal to x.