From 2fd6b5367c233f2115c4a5640b56af8d4e1ec73c Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Fri, 13 Mar 2026 19:35:26 +0800 Subject: [PATCH 1/5] Use hidden friends, defaulted comparison and three-way comparison --- cppwinrt/code_writers.h | 14 +---- strings/base_array.h | 41 ++++---------- strings/base_com_ptr.h | 73 +++++------------------- strings/base_fast_forward.h | 5 +- strings/base_foundation.h | 36 ++---------- strings/base_includes.h | 1 + strings/base_iterator.h | 25 +------- strings/base_reference_produce.h | 6 -- strings/base_reference_produce_1.h | 3 - strings/base_string.h | 57 ++++++++++++++++++- strings/base_string_operators.h | 91 ------------------------------ strings/base_types.h | 38 ++++++++----- strings/base_weak_ref.h | 48 ++++------------ strings/base_windows.h | 91 +++++++++++++++--------------- 14 files changed, 172 insertions(+), 357 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index c2c1c4893..9ac9caaaf 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1458,11 +1458,6 @@ namespace cppwinrt { return Key() == other.Key() && Value() == other.Value(); } - - bool operator!=(Windows::Foundation::Collections::IKeyValuePair const& other) const - { - return !(*this == other); - } )"); } else if (type_name == "Windows.Foundation.Collections.IMapView`2") @@ -2913,10 +2908,6 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { return%; } - inline bool operator!=(% const& left, % const& right)% - { - return !(left == right); - } )"; if (types.empty()) @@ -3001,10 +2992,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable name, name, is_noexcept, - bind(type.fields), - name, - name, - is_noexcept); + bind(type.fields)); for (auto&& field : type.fields) { diff --git a/strings/base_array.h b/strings/base_array.h index 426330f45..3b46f26a9 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -76,6 +76,18 @@ WINRT_EXPORT namespace winrt array_view(other.data(), other.size()) {} + template , std::remove_cv_t>, int> = 0> + bool operator==(array_view const& right) const noexcept + { + return std::equal(begin(), end(), right.begin(), right.end()); + } + + template , std::remove_cv_t>, int> = 0> + std::weak_ordering operator<=>(array_view const& right) const noexcept + { + return std::lexicographical_compare_three_way(begin(), end(), right.begin(), right.end()); + } + reference operator[](size_type const pos) noexcept { WINRT_ASSERT(pos < size()); @@ -400,35 +412,6 @@ WINRT_EXPORT namespace winrt template com_array(std::span const& value) -> com_array>; - namespace impl - { - template - inline constexpr bool array_comparable = std::is_same_v, std::remove_cv_t>; - } - - template , int> = 0> - bool operator==(array_view const& left, array_view const& right) noexcept - { - return std::equal(left.begin(), left.end(), right.begin(), right.end()); - } - - template , int> = 0> - bool operator<(array_view const& left, array_view const& right) noexcept - { - return std::lexicographical_compare(left.begin(), left.end(), right.begin(), right.end()); - } - - template , int> = 0> - bool operator!=(array_view const& left, array_view const& right) noexcept { return !(left == right); } - template , int> = 0> - bool operator>(array_view const& left, array_view const& right) noexcept { return right < left; } - template , int> = 0> - bool operator<=(array_view const& left, array_view const& right) noexcept { return !(right < left); } - template , int> = 0> - bool operator>=(array_view const& left, array_view const& right) noexcept { return !(left < right); } - template auto get_abi(array_view object) noexcept { diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 0f02fabeb..c82323988 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -68,6 +68,19 @@ WINRT_EXPORT namespace winrt release_ref(); } + bool operator==(com_ptr const& other) const noexcept = default; + auto operator<=>(com_ptr const& other) const noexcept = default; + + bool operator==(std::nullptr_t) const noexcept + { + return m_ptr == nullptr; + } + + friend bool operator==(std::nullptr_t, com_ptr const& right) noexcept + { + return right == nullptr; + } + com_ptr& operator=(com_ptr const& other) noexcept { copy_ref(other.m_ptr); @@ -287,66 +300,6 @@ WINRT_EXPORT namespace winrt { return object.detach(); } - - template - bool operator==(com_ptr const& left, com_ptr const& right) noexcept - { - return get_abi(left) == get_abi(right); - } - - template - bool operator==(com_ptr const& left, std::nullptr_t) noexcept - { - return get_abi(left) == nullptr; - } - - template - bool operator==(std::nullptr_t, com_ptr const& right) noexcept - { - return nullptr == get_abi(right); - } - - template - bool operator!=(com_ptr const& left, com_ptr const& right) noexcept - { - return !(left == right); - } - - template - bool operator!=(com_ptr const& left, std::nullptr_t) noexcept - { - return !(left == nullptr); - } - - template - bool operator!=(std::nullptr_t, com_ptr const& right) noexcept - { - return !(nullptr == right); - } - - template - bool operator<(com_ptr const& left, com_ptr const& right) noexcept - { - return get_abi(left) < get_abi(right); - } - - template - bool operator>(com_ptr const& left, com_ptr const& right) noexcept - { - return right < left; - } - - template - bool operator<=(com_ptr const& left, com_ptr const& right) noexcept - { - return !(right < left); - } - - template - bool operator>=(com_ptr const& left, com_ptr const& right) noexcept - { - return !(left < right); - } } WINRT_EXPORT namespace winrt::impl diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index e1496070a..ac57c76c1 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -40,10 +40,7 @@ WINRT_EXPORT namespace winrt::impl std::uint16_t Data2; std::uint16_t Data3; std::uint8_t Data4[8]; - inline bool operator!=(guid const& right) const noexcept - { - return std::memcmp(this, &right, sizeof(guid)); - } + constexpr bool operator==(guid const&) const noexcept = default; }; struct WINRT_IMPL_FF_NOVTABLE WINRT_IMPL_FF_PUBLIC inspectable diff --git a/strings/base_foundation.h b/strings/base_foundation.h index 083252753..23375858e 100644 --- a/strings/base_foundation.h +++ b/strings/base_foundation.h @@ -24,17 +24,9 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } #endif - }; - - constexpr bool operator==(Point const& left, Point const& right) noexcept - { - return left.X == right.X && left.Y == right.Y; - } - constexpr bool operator!=(Point const& left, Point const& right) noexcept - { - return !(left == right); - } + constexpr bool operator==(Point const&) const noexcept = default; + }; struct Size { @@ -59,17 +51,9 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } #endif - }; - - constexpr bool operator==(Size const& left, Size const& right) noexcept - { - return left.Width == right.Width && left.Height == right.Height; - } - constexpr bool operator!=(Size const& left, Size const& right) noexcept - { - return !(left == right); - } + constexpr bool operator==(Size const&) const noexcept = default; + }; struct Rect { @@ -87,17 +71,9 @@ WINRT_EXPORT namespace winrt::Windows::Foundation constexpr Rect(Point const& point, Size const& size) noexcept : X(point.X), Y(point.Y), Width(size.Width), Height(size.Height) {} - }; - constexpr bool operator==(Rect const& left, Rect const& right) noexcept - { - return left.X == right.X && left.Y == right.Y && left.Width == right.Width && left.Height == right.Height; - } - - constexpr bool operator!=(Rect const& left, Rect const& right) noexcept - { - return !(left == right); - } + constexpr bool operator==(Rect const&) const noexcept = default; + }; } WINRT_EXPORT namespace winrt::impl diff --git a/strings/base_includes.h b/strings/base_includes.h index 84c11379c..56e27e109 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -42,6 +42,7 @@ // C++ 20 headers #include +#include #include #include #include diff --git a/strings/base_iterator.h b/strings/base_iterator.h index 46c0c6b63..e6670327d 100644 --- a/strings/base_iterator.h +++ b/strings/base_iterator.h @@ -87,31 +87,10 @@ WINRT_EXPORT namespace winrt::impl return m_index == other.m_index; } - bool operator<(fast_iterator const& other) const noexcept + auto operator<=>(fast_iterator const& other) const noexcept { WINRT_ASSERT(m_collection == other.m_collection); - return m_index < other.m_index; - } - - bool operator>(fast_iterator const& other) const noexcept - { - WINRT_ASSERT(m_collection == other.m_collection); - return m_index > other.m_index; - } - - bool operator!=(fast_iterator const& other) const noexcept - { - return !(*this == other); - } - - bool operator<=(fast_iterator const& other) const noexcept - { - return !(*this > other); - } - - bool operator>=(fast_iterator const& other) const noexcept - { - return !(*this < other); + return m_index <=> other.m_index; } friend fast_iterator operator+(difference_type n, fast_iterator it) noexcept diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index c341e8d20..454ac4b2c 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -412,12 +412,6 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return left.Value() == right.Value(); } - - template - bool operator!=(IReference const& left, IReference const& right) - { - return !(left == right); - } } WINRT_EXPORT namespace winrt::impl diff --git a/strings/base_reference_produce_1.h b/strings/base_reference_produce_1.h index 0eb9b4b70..db857446e 100644 --- a/strings/base_reference_produce_1.h +++ b/strings/base_reference_produce_1.h @@ -3,7 +3,4 @@ WINRT_EXPORT namespace winrt::Windows::Foundation { template bool operator==(IReference const& left, IReference const& right); - - template - bool operator!=(IReference const& left, IReference const& right); } diff --git a/strings/base_string.h b/strings/base_string.h index 1e76e9a55..7b11acdf2 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -221,6 +221,61 @@ WINRT_EXPORT namespace winrt return *this = hstring{ value }; } + friend bool operator==(hstring const& left, hstring const& right) noexcept + { + return std::wstring_view(left) == std::wstring_view(right); + } + + friend std::strong_ordering operator<=>(hstring const& left, hstring const& right) noexcept + { + return std::wstring_view(left) <=> std::wstring_view(right); + } + + friend bool operator==(hstring const& left, std::wstring const& right) noexcept + { + return std::wstring_view(left) == right; + } + + friend std::strong_ordering operator<=>(hstring const& left, std::wstring const& right) noexcept + { + return std::wstring_view(left) <=> std::wstring_view(right); + } + + friend bool operator==(std::wstring const& left, hstring const& right) noexcept + { + return left == std::wstring_view(right); + } + + friend std::strong_ordering operator<=>(std::wstring const& left, hstring const& right) noexcept + { + return std::wstring_view(left) <=> std::wstring_view(right); + } + + friend bool operator==(hstring const& left, wchar_t const* right) noexcept + { + return std::wstring_view(left) == right; + } + + friend std::strong_ordering operator<=>(hstring const& left, wchar_t const* right) noexcept + { + return std::wstring_view(left) <=> std::wstring_view(right); + } + + friend bool operator==(wchar_t const* left, hstring const& right) noexcept + { + return left == std::wstring_view(right); + } + + friend std::strong_ordering operator<=>(wchar_t const* left, hstring const& right) noexcept + { + return std::wstring_view(left) <=> std::wstring_view(right); + } + + friend bool operator==(hstring const&, std::nullptr_t) = delete; + friend bool operator==(std::nullptr_t, hstring const&) = delete; + friend std::strong_ordering operator<=>(hstring const&, std::nullptr_t) = delete; + friend std::strong_ordering operator<=>(std::nullptr_t, hstring const&) = delete; + void clear() noexcept { m_handle.close(); @@ -234,7 +289,7 @@ WINRT_EXPORT namespace winrt } else { - return { L"", 0 }; + return {}; } } diff --git a/strings/base_string_operators.h b/strings/base_string_operators.h index c9e50fe88..aa9c71c95 100644 --- a/strings/base_string_operators.h +++ b/strings/base_string_operators.h @@ -1,97 +1,6 @@ WINRT_EXPORT namespace winrt { - inline bool operator==(hstring const& left, hstring const& right) noexcept - { - return std::wstring_view(left) == std::wstring_view(right); - } - - inline bool operator==(hstring const& left, std::wstring const& right) noexcept - { - return std::wstring_view(left) == right; - } - - inline bool operator==(std::wstring const& left, hstring const& right) noexcept - { - return left == std::wstring_view(right); - } - - inline bool operator==(hstring const& left, wchar_t const* right) noexcept - { - return std::wstring_view(left) == right; - } - - inline bool operator==(wchar_t const* left, hstring const& right) noexcept - { - return left == std::wstring_view(right); - } - - bool operator==(hstring const& left, std::nullptr_t) = delete; - - bool operator==(std::nullptr_t, hstring const& right) = delete; - - inline bool operator<(hstring const& left, hstring const& right) noexcept - { - return std::wstring_view(left) < std::wstring_view(right); - } - - inline bool operator<(std::wstring const& left, hstring const& right) noexcept - { - return left < std::wstring_view(right); - } - - inline bool operator<(hstring const& left, std::wstring const& right) noexcept - { - return std::wstring_view(left) < right; - } - - inline bool operator<(hstring const& left, wchar_t const* right) noexcept - { - return std::wstring_view(left) < right; - } - - inline bool operator<(wchar_t const* left, hstring const& right) noexcept - { - return left < std::wstring_view(right); - } - - bool operator<(hstring const& left, std::nullptr_t) = delete; - - bool operator<(std::nullptr_t, hstring const& right) = delete; - inline bool operator!=(hstring const& left, hstring const& right) noexcept { return !(left == right); } - inline bool operator>(hstring const& left, hstring const& right) noexcept { return right < left; } - inline bool operator<=(hstring const& left, hstring const& right) noexcept { return !(right < left); } - inline bool operator>=(hstring const& left, hstring const& right) noexcept { return !(left < right); } - - inline bool operator!=(hstring const& left, std::wstring const& right) noexcept { return !(left == right); } - inline bool operator>(hstring const& left, std::wstring const& right) noexcept { return right < left; } - inline bool operator<=(hstring const& left, std::wstring const& right) noexcept { return !(right < left); } - inline bool operator>=(hstring const& left, std::wstring const& right) noexcept { return !(left < right); } - - inline bool operator!=(std::wstring const& left, hstring const& right) noexcept { return !(left == right); } - inline bool operator>(std::wstring const& left, hstring const& right) noexcept { return right < left; } - inline bool operator<=(std::wstring const& left, hstring const& right) noexcept { return !(right < left); } - inline bool operator>=(std::wstring const& left, hstring const& right) noexcept { return !(left < right); } - - inline bool operator!=(hstring const& left, wchar_t const* right) noexcept { return !(left == right); } - inline bool operator>(hstring const& left, wchar_t const* right) noexcept { return right < left; } - inline bool operator<=(hstring const& left, wchar_t const* right) noexcept { return !(right < left); } - inline bool operator>=(hstring const& left, wchar_t const* right) noexcept { return !(left < right); } - - inline bool operator!=(wchar_t const* left, hstring const& right) noexcept { return !(left == right); } - inline bool operator>(wchar_t const* left, hstring const& right) noexcept { return right < left; } - inline bool operator<=(wchar_t const* left, hstring const& right) noexcept { return !(right < left); } - inline bool operator>=(wchar_t const* left, hstring const& right) noexcept { return !(left < right); } - - bool operator!=(hstring const& left, std::nullptr_t right) = delete; - bool operator>(hstring const& left, std::nullptr_t right) = delete; - bool operator<=(hstring const& left, std::nullptr_t right) = delete; - bool operator>=(hstring const& left, std::nullptr_t right) = delete; - - bool operator!=(std::nullptr_t left, hstring const& right) = delete; - bool operator>(std::nullptr_t left, hstring const& right) = delete; - bool operator<=(std::nullptr_t left, hstring const& right) = delete; - bool operator>=(std::nullptr_t left, hstring const& right) = delete; } WINRT_EXPORT namespace winrt::impl diff --git a/strings/base_types.h b/strings/base_types.h index dc2b13632..3bced1ed5 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -166,6 +166,29 @@ WINRT_EXPORT namespace winrt { } + constexpr bool operator==(guid const& other) const noexcept = default; + + constexpr auto operator<=>(guid const& other) const noexcept + { + #if __cpp_if_consteval >= 202106L + if consteval + #else + if (std::is_constant_evaluated()) + #endif + { + if (auto cmp = Data1 <=> other.Data1; cmp != 0) return cmp; + if (auto cmp = Data2 <=> other.Data2; cmp != 0) return cmp; + if (auto cmp = Data3 <=> other.Data3; cmp != 0) return cmp; + for (std::size_t i = 0u; i != 8u; ++i) + if (auto cmp = Data4[i] <=> other.Data4[i]; cmp != 0) return cmp; + return std::strong_ordering::equal; + } + else + { + return std::memcmp(this, &other, sizeof(guid)) <=> 0; + } + } + private: template constexpr static guid convert(T const& value) noexcept @@ -175,21 +198,6 @@ WINRT_EXPORT namespace winrt }; } }; - - inline bool operator==(guid const& left, guid const& right) noexcept - { - return !std::memcmp(&left, &right, sizeof(left)); - } - - inline bool operator!=(guid const& left, guid const& right) noexcept - { - return !(left == right); - } - - inline bool operator<(guid const& left, guid const& right) noexcept - { - return std::memcmp(&left, &right, sizeof(left)) < 0; - } } WINRT_EXPORT namespace winrt::Windows::Foundation diff --git a/strings/base_weak_ref.h b/strings/base_weak_ref.h index bc480ec2d..efaa039b6 100644 --- a/strings/base_weak_ref.h +++ b/strings/base_weak_ref.h @@ -48,6 +48,18 @@ WINRT_EXPORT namespace winrt return static_cast(m_ref); } + bool operator==(weak_ref const& other) const noexcept = default; + + bool operator==(std::nullptr_t) const noexcept + { + return m_ref == nullptr; + } + + friend bool operator==(std::nullptr_t, weak_ref const& right) noexcept + { + return right == nullptr; + } + private: template @@ -78,42 +90,6 @@ WINRT_EXPORT namespace winrt { }; - template - inline bool operator==(weak_ref const& left, weak_ref const& right) noexcept - { - return get_abi(left) == get_abi(right); - } - - template - inline bool operator==(weak_ref const& left, std::nullptr_t) noexcept - { - return get_abi(left) == nullptr; - } - - template - inline bool operator==(std::nullptr_t, weak_ref const& right) noexcept - { - return nullptr == get_abi(right); - } - - template - inline bool operator!=(weak_ref const& left, weak_ref const& right) noexcept - { - return !(left == right); - } - - template - inline bool operator!=(weak_ref const& left, std::nullptr_t) noexcept - { - return !(left == nullptr); - } - - template - inline bool operator!=(std::nullptr_t, weak_ref const& right) noexcept - { - return !(nullptr == right); - } - template weak_ref> make_weak(T const& object) { diff --git a/strings/base_windows.h b/strings/base_windows.h index d648a084a..1de7c54a9 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -262,6 +262,51 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return m_ptr->QueryInterface(id, result); } + bool operator==(IUnknown const& right) const noexcept + { + if (m_ptr == right.m_ptr) + { + return true; + } + + if (!(*this) || !right) + { + return false; + } + + auto const left_identity = try_as(); + auto const right_identity = right.try_as(); + return left_identity.m_ptr == right_identity.m_ptr; + } + + std::strong_ordering operator<=>(IUnknown const& right) const noexcept + { + void* const left_abi = m_ptr; + void* const right_abi = right.m_ptr; + + if (left_abi == right_abi) + { + return std::strong_ordering::equal; + } + + if (!(*this) || !right) + { + return left_abi < right_abi ? std::strong_ordering::less : std::strong_ordering::greater; + } + + auto const left_object_identity = try_as(); + auto const right_object_identity = right.try_as(); + void* const left_identity = left_object_identity.m_ptr; + void* const right_identity = right_object_identity.m_ptr; + + if (left_identity == right_identity) + { + return std::strong_ordering::equal; + } + + return left_identity < right_identity ? std::strong_ordering::less : std::strong_ordering::greater; + } + friend void swap(IUnknown& left, IUnknown& right) noexcept { std::swap(left.m_ptr, right.m_ptr); @@ -399,52 +444,6 @@ WINRT_EXPORT namespace winrt WINRT_EXPORT namespace winrt::Windows::Foundation { - inline bool operator==(IUnknown const& left, IUnknown const& right) noexcept - { - if (get_abi(left) == get_abi(right)) - { - return true; - } - if (!left || !right) - { - return false; - } - return get_abi(left.try_as()) == get_abi(right.try_as()); - } - - inline bool operator!=(IUnknown const& left, IUnknown const& right) noexcept - { - return !(left == right); - } - - inline bool operator<(IUnknown const& left, IUnknown const& right) noexcept - { - if (get_abi(left) == get_abi(right)) - { - return false; - } - if (!left || !right) - { - return get_abi(left) < get_abi(right); - } - return get_abi(left.try_as()) < get_abi(right.try_as()); - } - - inline bool operator>(IUnknown const& left, IUnknown const& right) noexcept - { - return right < left; - } - - inline bool operator<=(IUnknown const& left, IUnknown const& right) noexcept - { - return !(right < left); - } - - inline bool operator>=(IUnknown const& left, IUnknown const& right) noexcept - { - return !(left < right); - } - struct IInspectable : IUnknown { IInspectable(std::nullptr_t = nullptr) noexcept {} From 4929bdb39127432beab55afc4ffc924325e5fe64 Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Fri, 13 Mar 2026 22:12:19 +0800 Subject: [PATCH 2/5] Minor tweak --- strings/base_string.h | 3 ++- strings/base_types.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/strings/base_string.h b/strings/base_string.h index 7b11acdf2..a11f725e2 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -289,7 +289,8 @@ WINRT_EXPORT namespace winrt } else { - return {}; + // NB: https://github.com/microsoft/cppwinrt/issues/1527 + return { L"", 0 }; } } diff --git a/strings/base_types.h b/strings/base_types.h index 3bced1ed5..7684dfa3a 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -170,7 +170,7 @@ WINRT_EXPORT namespace winrt constexpr auto operator<=>(guid const& other) const noexcept { - #if __cpp_if_consteval >= 202106L + #if defined(__cpp_if_consteval) && __cpp_if_consteval >= 202106L if consteval #else if (std::is_constant_evaluated()) From 5e2d598b3532f65cd796e87d188ed2cc0a3e9402 Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Fri, 13 Mar 2026 23:08:27 +0800 Subject: [PATCH 3/5] Try fix --- cppwinrt/code_writers.h | 9 --------- strings/base_collections.h | 6 ++++++ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 9ac9caaaf..0e78617cb 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1449,15 +1449,6 @@ namespace cppwinrt { ++(*this); } -)"); - } - else if (type_name == "Windows.Foundation.Collections.IKeyValuePair`2") - { - w.write(R"( - bool operator==(Windows::Foundation::Collections::IKeyValuePair const& other) const - { - return Key() == other.Key() && Value() == other.Value(); - } )"); } else if (type_name == "Windows.Foundation.Collections.IMapView`2") diff --git a/strings/base_collections.h b/strings/base_collections.h index 7d8dc2e77..747ec1f31 100644 --- a/strings/base_collections.h +++ b/strings/base_collections.h @@ -48,6 +48,12 @@ WINRT_EXPORT namespace winrt::impl template struct is_key_value_pair> : std::true_type {}; + template + bool operator==(wfc::IKeyValuePair const& left, wfc::IKeyValuePair const& right) + { + return left.Key() == right.Key() && left.Value() == right.Value(); + } + struct input_scope { void invalidate_scope() noexcept From 97a7cc4ac1edf7948412af9d773de65c6fe3144c Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Sat, 14 Mar 2026 00:20:56 +0800 Subject: [PATCH 4/5] Restore hidden friend --- cppwinrt/code_writers.h | 17 +++++++++++++++++ strings/base_collections.h | 6 ------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 0e78617cb..cadc70339 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2513,6 +2513,19 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable } } + static void write_interface_equal_operator(writer& w, TypeDef const& type) + { + if (remove_tick(type.TypeName()) == "IKeyValuePair") + { + w.write(R"( + friend bool operator==(IKeyValuePair const& left, IKeyValuePair const& right) + { + return left.Key() == right.Key() && left.Value() == right.Value(); + } +)"); + } + } + static void write_class_usings(writer& w, TypeDef const& type) { auto type_name = type.TypeName(); @@ -2581,6 +2594,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { %(std::nullptr_t = nullptr) noexcept {} %(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Foundation::IInspectable(ptr, take_ownership_from_abi) {} +% %% }; )"; @@ -2591,6 +2605,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable type_name, type_name, bind(type), + bind(type), bind(type)); } else @@ -2604,6 +2619,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable {% %(std::nullptr_t = nullptr) noexcept {} %(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Foundation::IInspectable(ptr, take_ownership_from_abi) {} +% %% }; )"; @@ -2616,6 +2632,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable type_name, type_name, bind(type), + bind(type), bind(type)); } } diff --git a/strings/base_collections.h b/strings/base_collections.h index 747ec1f31..7d8dc2e77 100644 --- a/strings/base_collections.h +++ b/strings/base_collections.h @@ -48,12 +48,6 @@ WINRT_EXPORT namespace winrt::impl template struct is_key_value_pair> : std::true_type {}; - template - bool operator==(wfc::IKeyValuePair const& left, wfc::IKeyValuePair const& right) - { - return left.Key() == right.Key() && left.Value() == right.Value(); - } - struct input_scope { void invalidate_scope() noexcept From b73d5a21a803958c1c1996cc49b5fd6a597a31b5 Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Sat, 14 Mar 2026 00:56:44 +0800 Subject: [PATCH 5/5] Test member --- cppwinrt/code_writers.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index cadc70339..4a0c76f11 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2517,10 +2517,9 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { if (remove_tick(type.TypeName()) == "IKeyValuePair") { - w.write(R"( - friend bool operator==(IKeyValuePair const& left, IKeyValuePair const& right) + w.write(R"( bool operator==(IKeyValuePair const& other) const { - return left.Key() == right.Key() && left.Value() == right.Value(); + return this->Key() == other.Key() && this->Value() == other.Value(); } )"); }