Fixes #119721

This fixes a C++23 compliance issue where std::tuple<> cannot be compared
with std::array<T, 0>. Both are empty tuple-like types and should be
comparable according to the C++23 standard.

The fix adds the missing comparison operators:
- operator== and operator!= (return true and false respectively)
- operator<, operator<=, operator>, operator>= (follow ordering rules for empty 
types)
- operator<=> (returns strong_ordering::equal)

This resolves the 'rejects-valid' bug where GCC was rejecting valid C++23 code
that Clang with libc++ already supports correctly.

libstdc++-v3/ChangeLog:

        * include/std/tuple: Add comparison operators between tuple<> and 
array<T, 0>.

Signed-off-by: Osama Abdelkader <[email protected]>
---
 libstdc++-v3/include/std/tuple | 88 ++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 0ca616f1b..d3621dd16 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -1880,6 +1880,94 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          using _Cat = typename 
__tuple_like_common_comparison_category<_UTuple>::type;
          return std::__tuple_cmp<_Cat>(__t, __u, 
index_sequence_for<_Elements...>());
        }
+
+  // Comparison operators between tuple<> and array<T, 0>
+  // These are needed because both are empty tuple-like types in C++23
+  
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator==(const tuple<>&, const array<_Tp, 0>&)
+    { return true; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator==(const array<_Tp, 0>&, const tuple<>&)
+    { return true; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator!=(const tuple<>&, const array<_Tp, 0>&)
+    { return false; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator!=(const array<_Tp, 0>&, const tuple<>&)
+    { return false; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator<(const tuple<>&, const array<_Tp, 0>&)
+    { return false; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator<(const array<_Tp, 0>&, const tuple<>&)
+    { return false; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator<=(const tuple<>&, const array<_Tp, 0>&)
+    { return true; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator<=(const array<_Tp, 0>&, const tuple<>&)
+    { return true; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator>(const tuple<>&, const array<_Tp, 0>&)
+    { return false; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator>(const array<_Tp, 0>&, const tuple<>&)
+    { return false; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator>=(const tuple<>&, const array<_Tp, 0>&)
+    { return true; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator>=(const array<_Tp, 0>&, const tuple<>&)
+    { return true; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr strong_ordering
+    operator<=>(const tuple<>&, const array<_Tp, 0>&)
+    { return strong_ordering::equal; }
+
+  template<typename _Tp>
+    [[nodiscard]]
+    constexpr strong_ordering
+    operator<=>(const array<_Tp, 0>&, const tuple<>&)
+    { return strong_ordering::equal; }
+
 #endif // C++23
 
 #else // ! (concepts && consteval)
-- 
2.43.0

Reply via email to