From b1911bf6bff4829c25618c7fc0c55e1626d17745 Mon Sep 17 00:00:00 2001 From: Matthew Wozniczka Date: Tue, 2 Dec 2025 17:46:37 -0800 Subject: [PATCH 1/4] [ICU-23271] Fix the error `include\unicode\unistr.h(2228,31): error C2668: 'sbicu_77::internal::toU16StringView': ambiguous call to overloaded function` when compiling with visual studio 2022 when calling `template>> UnicodeString::operator+(const UnicodeString&, const S&)` w/ `S` being a subclass of `UnicodeString` --- icu4c/source/common/unicode/char16ptr.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/icu4c/source/common/unicode/char16ptr.h b/icu4c/source/common/unicode/char16ptr.h index 049de9efee81..f7af8b6dfa21 100644 --- a/icu4c/source/common/unicode/char16ptr.h +++ b/icu4c/source/common/unicode/char16ptr.h @@ -381,9 +381,12 @@ U_NAMESPACE_BEGIN * Is T convertible to a std::u16string_view or some other 16-bit string view? * @internal */ +template +constexpr bool DirectlyConvertibleToU16StringView = std::is_convertible_v; + template constexpr bool ConvertibleToU16StringView = - std::is_convertible_v + DirectlyConvertibleToU16StringView #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000) || std::is_convertible_v> #endif @@ -394,10 +397,12 @@ constexpr bool ConvertibleToU16StringView = namespace internal { /** - * Pass-through overload. + * Pass-through overload for anything which is already implicitly convertible (including std::u16string_view itself). * @internal */ -inline std::u16string_view toU16StringView(std::u16string_view sv) { return sv; } +template >> +std::u16string_view toU16StringView(std::u16string_view sv) { return sv; } #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000) /** @@ -426,7 +431,8 @@ inline std::u16string_view toU16StringView(std::wstring_view sv) { * @internal */ template >>> + typename = typename std::enable_if_t && + !std::is_pointer_v>>> inline std::u16string_view toU16StringViewNullable(const T& text) { return toU16StringView(text); } @@ -436,7 +442,8 @@ inline std::u16string_view toU16StringViewNullable(const T& text) { * @internal */ template >>, + typename = typename std::enable_if_t && + std::is_pointer_v>>, typename = void> inline std::u16string_view toU16StringViewNullable(const T& text) { if (text == nullptr) return {}; // For backward compatibility. From 4b279c8fbbeb4abcb7fe24d8f42bdfdda56b20a1 Mon Sep 17 00:00:00 2001 From: Matthew Wozniczka Date: Tue, 2 Dec 2025 23:36:37 -0800 Subject: [PATCH 2/4] [ICU-23271] Revert changes to `enable_if` conditions on `toU16StringViewNullable` overloads (didn't notice these _weren't_ called `toU16StringView` earlier) from previous commit --- icu4c/source/common/unicode/char16ptr.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/icu4c/source/common/unicode/char16ptr.h b/icu4c/source/common/unicode/char16ptr.h index f7af8b6dfa21..5dc1ee4ece9b 100644 --- a/icu4c/source/common/unicode/char16ptr.h +++ b/icu4c/source/common/unicode/char16ptr.h @@ -431,9 +431,8 @@ inline std::u16string_view toU16StringView(std::wstring_view sv) { * @internal */ template && - !std::is_pointer_v>>> -inline std::u16string_view toU16StringViewNullable(const T& text) { + typename = typename std::enable_if_t>>> +std::u16string_view toU16StringViewNullable(const T& text) { return toU16StringView(text); } @@ -442,10 +441,9 @@ inline std::u16string_view toU16StringViewNullable(const T& text) { * @internal */ template && - std::is_pointer_v>>, + typename = typename std::enable_if_t>>, typename = void> -inline std::u16string_view toU16StringViewNullable(const T& text) { +std::u16string_view toU16StringViewNullable(const T& text) { if (text == nullptr) return {}; // For backward compatibility. return toU16StringView(text); } From 9785383e6c2c90313605daf6087ba194e1667c79 Mon Sep 17 00:00:00 2001 From: Matthew Wozniczka Date: Wed, 3 Dec 2025 14:39:29 -0800 Subject: [PATCH 3/4] =?UTF-8?q?[ICU-23271]=20Fix=20`couldn't=20deduce=20te?= =?UTF-8?q?mplate=20parameter=20=E2=80=98T=E2=80=99`=20compile=20errors=20?= =?UTF-8?q?related=20to=20my=20recent=20change=20(It's=20a=20bit=20strange?= =?UTF-8?q?=20it=20worked=20when=20=5Fusing=5F=20the=20header=20from=20our?= =?UTF-8?q?=20code=3F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- icu4c/source/common/unicode/char16ptr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icu4c/source/common/unicode/char16ptr.h b/icu4c/source/common/unicode/char16ptr.h index 5dc1ee4ece9b..8ea68bb1837e 100644 --- a/icu4c/source/common/unicode/char16ptr.h +++ b/icu4c/source/common/unicode/char16ptr.h @@ -402,7 +402,7 @@ namespace internal { */ template >> -std::u16string_view toU16StringView(std::u16string_view sv) { return sv; } +std::u16string_view toU16StringView(const T& text) { return text; } #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000) /** From feb41c7a9e3bf207bdd1b3417c0b798b47793485 Mon Sep 17 00:00:00 2001 From: Matthew Wozniczka Date: Thu, 4 Dec 2025 10:07:42 -0800 Subject: [PATCH 4/4] [ICU-23271] Remove recently-added `DirectlyConvertibleToU16StringView` in favour of direct use of `std::is_convertible_t` definition based on PR comment. --- icu4c/source/common/unicode/char16ptr.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/icu4c/source/common/unicode/char16ptr.h b/icu4c/source/common/unicode/char16ptr.h index 8ea68bb1837e..4715c93435bf 100644 --- a/icu4c/source/common/unicode/char16ptr.h +++ b/icu4c/source/common/unicode/char16ptr.h @@ -381,12 +381,9 @@ U_NAMESPACE_BEGIN * Is T convertible to a std::u16string_view or some other 16-bit string view? * @internal */ -template -constexpr bool DirectlyConvertibleToU16StringView = std::is_convertible_v; - template constexpr bool ConvertibleToU16StringView = - DirectlyConvertibleToU16StringView + std::is_convertible_v #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000) || std::is_convertible_v> #endif @@ -401,7 +398,7 @@ namespace internal { * @internal */ template >> + typename = typename std::enable_if_t>> std::u16string_view toU16StringView(const T& text) { return text; } #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)