mirror of
https://github.com/google/googletest.git
synced 2026-04-30 19:09:20 +08:00
Changed the way the char type is deducted for StringLike, eliminated function overloads in favor of if constexpr
This commit is contained in:
parent
c477238842
commit
f75b7dfcda
@ -913,8 +913,10 @@ struct ci_matcher_supported : std::false_type {};
|
||||
template<>
|
||||
struct ci_matcher_supported<char> : std::true_type {};
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
template<>
|
||||
struct ci_matcher_supported<wchar_t> : std::true_type {};
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
// String matchers.
|
||||
|
||||
@ -965,8 +967,14 @@ class [[nodiscard]] StrEqualityMatcher {
|
||||
bool MatchAndExplain(const MatcheeStringType& s,
|
||||
MatchResultListener* /* listener */) const {
|
||||
const StringType s2(s);
|
||||
const bool eq = MatchStrings(s2, ci_matcher_supported<typename StringType::value_type>{});
|
||||
return expect_eq_ == eq;
|
||||
if constexpr(ci_matcher_supported<typename StringType::value_type>::value) {
|
||||
const bool eq = CaseSensitive::value ?
|
||||
s2 == string_ : CaseInsensitiveStringEquals(s2, string_);
|
||||
return expect_eq_ == eq;
|
||||
} else {
|
||||
const bool eq = s2 == string_;
|
||||
return expect_eq_ == eq;
|
||||
}
|
||||
}
|
||||
|
||||
void DescribeTo(::std::ostream* os) const {
|
||||
@ -978,21 +986,10 @@ class [[nodiscard]] StrEqualityMatcher {
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename S>
|
||||
bool MatchStrings(const S& s2, std::true_type) const {
|
||||
return CaseSensitive::value ? s2 == string_
|
||||
: CaseInsensitiveStringEquals(s2, string_);
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
bool MatchStrings(const S& s2, std::false_type) const {
|
||||
return s2 == string_;
|
||||
}
|
||||
|
||||
void DescribeToHelper(bool expect_eq, ::std::ostream* os) const {
|
||||
*os << (expect_eq ? "is " : "isn't ");
|
||||
*os << "equal to ";
|
||||
if (!CaseSensitive::value) {
|
||||
if constexpr(!CaseSensitive::value) {
|
||||
*os << "(ignoring case) ";
|
||||
}
|
||||
UniversalPrint(string_, os);
|
||||
@ -4808,7 +4805,7 @@ internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
|
||||
|
||||
// Matches a string equal to str.
|
||||
template <typename T = std::string,
|
||||
typename CharT = internal::char_type_traits_t<T>>
|
||||
typename CharT = internal::get_char_type_t<T>>
|
||||
PolymorphicMatcher<internal::StrEqualityMatcher<std::basic_string<CharT>>> StrEq(
|
||||
const internal::StringLike<T>& str) {
|
||||
return MakePolymorphicMatcher(
|
||||
@ -4817,7 +4814,7 @@ PolymorphicMatcher<internal::StrEqualityMatcher<std::basic_string<CharT>>> StrEq
|
||||
|
||||
// Matches a string not equal to str.
|
||||
template <typename T = std::string,
|
||||
typename CharT = internal::char_type_traits_t<T>>
|
||||
typename CharT = internal::get_char_type_t<T>>
|
||||
PolymorphicMatcher<internal::StrEqualityMatcher<std::basic_string<CharT>>> StrNe(
|
||||
const internal::StringLike<T>& str) {
|
||||
return MakePolymorphicMatcher(
|
||||
@ -4826,7 +4823,7 @@ PolymorphicMatcher<internal::StrEqualityMatcher<std::basic_string<CharT>>> StrNe
|
||||
|
||||
// Matches a string equal to str, ignoring case.
|
||||
template <typename T = std::string,
|
||||
typename CharT = internal::char_type_traits_t<T>>
|
||||
typename CharT = internal::get_char_type_t<T>>
|
||||
PolymorphicMatcher<internal::StrEqualityMatcher<std::basic_string<CharT>, std::false_type>> StrCaseEq(
|
||||
const internal::StringLike<T>& str) {
|
||||
return MakePolymorphicMatcher(
|
||||
@ -4836,7 +4833,7 @@ PolymorphicMatcher<internal::StrEqualityMatcher<std::basic_string<CharT>, std::f
|
||||
|
||||
// Matches a string not equal to str, ignoring case.
|
||||
template <typename T = std::string,
|
||||
typename CharT = internal::char_type_traits_t<T>>
|
||||
typename CharT = internal::get_char_type_t<T>>
|
||||
PolymorphicMatcher<internal::StrEqualityMatcher<std::basic_string<CharT>, std::false_type>> StrCaseNe(
|
||||
const internal::StringLike<T>& str) {
|
||||
return MakePolymorphicMatcher(
|
||||
@ -4847,7 +4844,7 @@ PolymorphicMatcher<internal::StrEqualityMatcher<std::basic_string<CharT>, std::f
|
||||
// Creates a matcher that matches any string, std::string, or C string
|
||||
// that contains the given substring.
|
||||
template <typename T = std::string,
|
||||
typename CharT = internal::char_type_traits_t<T>>
|
||||
typename CharT = internal::get_char_type_t<T>>
|
||||
PolymorphicMatcher<internal::HasSubstrMatcher<std::basic_string<CharT>>> HasSubstr(
|
||||
const internal::StringLike<T>& substring) {
|
||||
return MakePolymorphicMatcher(
|
||||
@ -4856,7 +4853,7 @@ PolymorphicMatcher<internal::HasSubstrMatcher<std::basic_string<CharT>>> HasSubs
|
||||
|
||||
// Matches a string that starts with 'prefix' (case-sensitive).
|
||||
template <typename T = std::string,
|
||||
typename CharT = internal::char_type_traits_t<T>>
|
||||
typename CharT = internal::get_char_type_t<T>>
|
||||
PolymorphicMatcher<internal::StartsWithMatcher<std::basic_string<CharT>>> StartsWith(
|
||||
const internal::StringLike<T>& prefix) {
|
||||
return MakePolymorphicMatcher(
|
||||
@ -4865,7 +4862,7 @@ PolymorphicMatcher<internal::StartsWithMatcher<std::basic_string<CharT>>> Starts
|
||||
|
||||
// Matches a string that ends with 'suffix' (case-sensitive).
|
||||
template <typename T = std::string,
|
||||
typename CharT = internal::char_type_traits_t<T>>
|
||||
typename CharT = internal::get_char_type_t<T>>
|
||||
PolymorphicMatcher<internal::EndsWithMatcher<std::basic_string<CharT>>> EndsWith(
|
||||
const internal::StringLike<T>& suffix) {
|
||||
return MakePolymorphicMatcher(
|
||||
|
||||
@ -1364,6 +1364,57 @@ TEST(StrEqTest, AllowsWideChars) {
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
}
|
||||
|
||||
TEST(StrEqTest, AllowsCustomStringLikeType) {
|
||||
struct MyString {
|
||||
operator std::string() const { return std::string("Hello"); }
|
||||
};
|
||||
|
||||
Matcher<const char*> m = StrEq(MyString{});
|
||||
EXPECT_TRUE(m.Matches("Hello"));
|
||||
EXPECT_FALSE(m.Matches("hello"));
|
||||
EXPECT_FALSE(m.Matches(nullptr));
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
struct MyWString {
|
||||
operator std::wstring() const { return std::wstring(L"Hello"); }
|
||||
};
|
||||
|
||||
Matcher<const wchar_t*> mw = StrEq(MyWString{});
|
||||
EXPECT_TRUE(mw.Matches(L"Hello"));
|
||||
EXPECT_FALSE(mw.Matches(L"hello"));
|
||||
EXPECT_FALSE(mw.Matches(nullptr));
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
struct MyU16String {
|
||||
operator std::u16string() const { return std::u16string(u"Hello"); }
|
||||
};
|
||||
|
||||
Matcher<const char16_t*> m16 = StrEq(MyU16String{});
|
||||
EXPECT_TRUE(m16.Matches(u"Hello"));
|
||||
EXPECT_FALSE(m16.Matches(u"hello"));
|
||||
EXPECT_FALSE(m16.Matches(nullptr));
|
||||
|
||||
struct MyU32String {
|
||||
operator std::u32string() const { return std::u32string(U"Hello"); }
|
||||
};
|
||||
|
||||
Matcher<const char32_t*> m32 = StrEq(MyU32String{});
|
||||
EXPECT_TRUE(m32.Matches(U"Hello"));
|
||||
EXPECT_FALSE(m32.Matches(U"hello"));
|
||||
EXPECT_FALSE(m32.Matches(nullptr));
|
||||
|
||||
#ifdef __cpp_lib_char8_t
|
||||
struct MyU8String {
|
||||
operator std::u8string() const { return std::u8string(u8"Hello"); }
|
||||
};
|
||||
|
||||
Matcher<const char8_t*> m8 = StrEq(MyU8String{});
|
||||
EXPECT_TRUE(m8.Matches(u8"Hello"));
|
||||
EXPECT_FALSE(m8.Matches(u8"hello"));
|
||||
EXPECT_FALSE(m8.Matches(nullptr));
|
||||
#endif // __cpp_lib_char8_t
|
||||
}
|
||||
|
||||
TEST(StrNeTest, MatchesUnequalString) {
|
||||
Matcher<const char*> m = StrNe("Hello");
|
||||
EXPECT_TRUE(m.Matches(""));
|
||||
|
||||
@ -815,64 +815,31 @@ class [[nodiscard]] ImplicitCastEqMatcher {
|
||||
StoredRhs stored_rhs_;
|
||||
};
|
||||
|
||||
// Backported std::remove_cvref_t (since C++20)
|
||||
template<typename T>
|
||||
struct remove_cvref {
|
||||
using type = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
template<typename T, typename CharT>
|
||||
struct maybe_stringish : std::bool_constant<std::is_constructible_v<std::basic_string<CharT>, T>> {
|
||||
using type = CharT;
|
||||
};
|
||||
|
||||
struct default_char_type : std::true_type
|
||||
{
|
||||
using type = char;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using remove_cvref_t = typename remove_cvref<T>::type;
|
||||
|
||||
// Character type detecting traits
|
||||
// It is used to deduct the CharT (Character Trait) out of
|
||||
// [const] char/wchar_t/char8_t/char16_t/char32_t *, basic_string<...>, basic_string_view<...>
|
||||
|
||||
template <typename T>
|
||||
struct is_char_type : std::false_type {};
|
||||
|
||||
template <> struct is_char_type<char> : std::true_type {};
|
||||
template <> struct is_char_type<char16_t> : std::true_type {};
|
||||
template <> struct is_char_type<char32_t> : std::true_type {};
|
||||
|
||||
using get_char_type_t = typename std::disjunction<
|
||||
maybe_stringish<T, char>,
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
template <> struct is_char_type<wchar_t> : std::true_type {};
|
||||
maybe_stringish<T, wchar_t>,
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
maybe_stringish<T, char16_t>,
|
||||
maybe_stringish<T, char32_t>,
|
||||
#ifdef __cpp_lib_char8_t
|
||||
template <> struct is_char_type<char8_t> : std::true_type {};
|
||||
maybe_stringish<T, char8_t>,
|
||||
#endif // __cpp_lib_char8_t
|
||||
default_char_type // we will default to char anyway
|
||||
>::type;
|
||||
|
||||
template <typename T>
|
||||
struct type_identity { using type = T; };
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct char_type_traits_impl {};
|
||||
|
||||
template <typename CharT, typename Traits, typename Alloc>
|
||||
struct char_type_traits_impl<std::basic_string<CharT, Traits, Alloc>,
|
||||
std::void_t<std::enable_if_t<is_char_type<std::remove_cv_t<CharT>>::value>>> :
|
||||
type_identity<CharT> {};
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
struct char_type_traits_impl<std::basic_string_view<CharT, Traits>,
|
||||
std::void_t<std::enable_if_t<is_char_type<std::remove_cv_t<CharT>>::value>>> :
|
||||
type_identity<CharT> {};
|
||||
|
||||
template <typename CharT>
|
||||
struct char_type_traits_impl<CharT*,
|
||||
std::void_t<std::enable_if_t<is_char_type<std::remove_cv_t<CharT>>::value>>> :
|
||||
type_identity<std::remove_cv_t<CharT>> {};
|
||||
|
||||
template <typename T>
|
||||
struct char_type_traits : char_type_traits_impl<std::decay_t<remove_cvref_t<T>>> {};
|
||||
|
||||
template<typename T>
|
||||
using char_type_traits_t = typename char_type_traits<T>::type;
|
||||
|
||||
template <typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_constructible_v<std::basic_string<char_type_traits_t<T>>, T>>>
|
||||
template<typename T, typename = std::enable_if_t<std::is_constructible_v<std::basic_string<get_char_type_t<T>>, T>>>
|
||||
using StringLike = T;
|
||||
|
||||
// Implements polymorphic matchers MatchesRegex(regex) and
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user