Skip to content

Extend support for StrEqualityMatcher class and factory functions for wide char strings#4926

Open
XAMeLeOH wants to merge 1 commit intogoogle:mainfrom
XAMeLeOH:feature/string-equality-matcher-support-wide-chars
Open

Extend support for StrEqualityMatcher class and factory functions for wide char strings#4926
XAMeLeOH wants to merge 1 commit intogoogle:mainfrom
XAMeLeOH:feature/string-equality-matcher-support-wide-chars

Conversation

@XAMeLeOH
Copy link

@XAMeLeOH XAMeLeOH commented Feb 5, 2026

Feature description

Extending support of wide characters for StrEqualityMatcher and factory functions using the class.

Feature request: #4912.

Analysis and design

StrEqualityMatcher and the factory functions using it support std::wstring, it's not implemented the same way it is done for std::string. For instance StrEq object for std::string can be created out of char *, std::string, std::string_view thanks to using internal::StringLike template alias. Whereas the version for std::wstring only supports const std::wstring&.

Also there absolutely no support for char[8|16|32]_t whatsoever.

Matcher / CharT char wchar_t char16_t char32_t char8_t
StrEq ✅*
StrNe ✅*
StrCaseEq ✅*
StrCaseNe ✅*
HasSubstr ✅*
StartsWith ✅*
EndsWith ✅*

* - does not support creation from a std::basic_string_view<>

Solution description

The solution proposed generalizes the std::string version of the class and functions for the whole variety of the character types.

Factory functions HasSubstr, StartsWith, EndsWith are also extended (atm lacking the tests).

Matcher / CharT char wchar_t char16_t char32_t char8_t
StrEq
StrNe
StrCaseEq ❌* ❌* ❌*
StrCaseNe ❌* ❌* ❌*
HasSubstr
StartsWith
EndsWith

* - Case insensitive comparison is not provided by the standard library, thus is not implemented here.

Areas affected

Public interface - factory functions (e.g. StrEq) are backward compatible.

Extended StringLike which is an internal type has been extended to include wide characters.

StrEqualityMatcher class (also an internal entity) has been changed the following way:

  • The c'tor argument case_sensitive was removed in favour of the template parameter. This was done in order to avoid calling case insensitive comparison functions for the character types that don't support such a comparison (char[8|16|32]_t).

@google-cla
Copy link

google-cla bot commented Feb 5, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@XAMeLeOH XAMeLeOH force-pushed the feature/string-equality-matcher-support-wide-chars branch 2 times, most recently from b2c80fd to 7b84bf4 Compare February 6, 2026 14:19
@XAMeLeOH XAMeLeOH marked this pull request as ready for review February 11, 2026 12:04
@XAMeLeOH
Copy link
Author

This PR resolves #4912

…Eq/StrCaseNe functions for strings based on the wide characters

Extended StringLike to support wide character types

Added more tests

Restricted possible char types
@XAMeLeOH XAMeLeOH force-pushed the feature/string-equality-matcher-support-wide-chars branch from 73e79ba to c477238 Compare February 11, 2026 13:43
*os << (expect_eq ? "is " : "isn't ");
*os << "equal to ";
if (!case_sensitive_) {
if (!CaseSensitive::value) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could now be constexpr-if if I'm not mistaken.
(a C++17 feature, which should not be a problem)

template <typename T,
typename = std::enable_if_t<
std::is_constructible_v<std::basic_string<char_type_traits_t<T>>, T>>>
using StringLike = T;
Copy link

@brandl-muc brandl-muc Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm reading it correctly, then you changed the meaning of StringLike.
Before, it would be defined for any type from which you could construct a std::string.
After, it is only defined for c strings, basic_strings and basic_string_views of any character type. This seems to betray the intention of StringLike, you basically could have used std::basic_string_view directly as it, too, supports all three types.

To phrase it differently, suppose my codebase had the following type with a conversion function:

class MyString {
  // implementation omitted

  operator std::string() const
};

Without having tested this, the compiler in my head says that I can do StrEq(MyString{ "foo" }, "foo") without your change, but I can't anymore with your change. It's thus a breaking change.

You probably need to do something along these lines:

template <typename T, typename CharT, typename = typename std::enable_if_t<
                          std::is_constructible_v<std::basic_string<CharT>, T>>>
using StringLike = T;

And then use it like so:

template <typename T = std::string,
          typename CharT = internal::char_type_traits_t<T>>
PolymorphicMatcher<internal::StrEqualityMatcher<std::basic_string<CharT>>> StrEq(
    const internal::StringLike<T, CharT>& str) {
  return MakePolymorphicMatcher(
      internal::StrEqualityMatcher<std::basic_string<CharT>>(std::basic_string<CharT>(str), true));
}

But as I'm not a maintainer and since there are no tests for such a class like MyString this can or cannot be OK, I simply can't say.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants