https://gcc.gnu.org/g:5a4f430006efeb58461402054e29b5ac5bd5ac5b

commit r16-4551-g5a4f430006efeb58461402054e29b5ac5bd5ac5b
Author: Osama Abdelkader <[email protected]>
Date:   Mon Oct 20 18:16:52 2025 +0300

    libstdc++: Add comparison operators between tuple<> and array<T, 0> 
[PR119721]
    
    This fixes the C++23 compliance issue where std::tuple<> cannot be compared
    with other empty tuple-like types such as std::array<T, 0>.
    
    The operators correctly allow comparison with array<T, 0> even when T is not
    comparable, because empty tuple-like types don't compare element values.
    
            PR libstdc++/119721
    
    libstdc++-v3/ChangeLog:
    
            * include/std/tuple (tuple<>::operator==, tuple<>::operator<=>):
            Define.
            * testsuite/23_containers/tuple/comparison_operators/119721.cc:
            New test.
    
    Reviewed-by: Jonathan Wakely <[email protected]>
    Reviewed-by: Tomasz KamiƄski <[email protected]>
    Signed-off-by: Osama Abdelkader <[email protected]>

Diff:
---
 libstdc++-v3/include/std/tuple                     | 16 ++++++
 .../tuple/comparison_operators/119721.cc           | 65 ++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 0ca616f1b4fb..c064a92df4c1 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -1999,6 +1999,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _Alloc>
        _GLIBCXX20_CONSTEXPR
        tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
+
+#if __cpp_lib_tuple_like // >= C++23
+      // Comparison operators for tuple<> with other empty tuple-like types
+      template<__tuple_like _UTuple>
+       requires (!__is_tuple_v<_UTuple> && tuple_size_v<_UTuple> == 0)
+      [[nodiscard]]
+      friend constexpr bool
+      operator==(const tuple&, const _UTuple&) noexcept
+      { return true; }
+
+      template<__tuple_like _UTuple>
+       requires (!__is_tuple_v<_UTuple> && tuple_size_v<_UTuple> == 0)
+      friend constexpr strong_ordering
+      operator<=>(const tuple&, const _UTuple&) noexcept
+      { return strong_ordering::equal; }
+#endif // C++23
     };
 
 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // 
!C++20
diff --git 
a/libstdc++-v3/testsuite/23_containers/tuple/comparison_operators/119721.cc 
b/libstdc++-v3/testsuite/23_containers/tuple/comparison_operators/119721.cc
new file mode 100644
index 000000000000..cad7ca005c43
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/tuple/comparison_operators/119721.cc
@@ -0,0 +1,65 @@
+// { dg-do compile { target c++23 } }
+// { dg-options "-std=c++23" }
+
+// Test for PR libstdc++/119721: tuple<> comparison with array<T, 0>
+
+#include <tuple>
+#include <array>
+#include <testsuite_hooks.h>
+#include <cassert>
+
+constexpr void
+test01()
+{
+  std::tuple<> t;
+  std::array<int, 0> a;
+
+  // Basic comparison should work
+  VERIFY( t == a );
+  VERIFY( a == t );
+  VERIFY( !(t != a) );
+  VERIFY( !(a != t) );
+
+  // Ordering comparisons should be equal
+  VERIFY( !(t < a) );
+  VERIFY( !(t > a) );
+  VERIFY( t <= a );
+  VERIFY( t >= a );
+  VERIFY( !(a < t) );
+  VERIFY( !(a > t) );
+  VERIFY( a <= t );
+  VERIFY( a >= t );
+
+  // Three-way comparison should return equal
+  VERIFY( (t <=> a) == std::strong_ordering::equal );
+  VERIFY( (a <=> t) == std::strong_ordering::equal );
+}
+
+constexpr void
+test02()
+{
+  // Test with non-comparable element type
+  struct NonComparable {
+    void operator==(const NonComparable&) const = delete;
+    void operator<=>(const NonComparable&) const = delete;
+  };
+
+  std::tuple<> t;
+  std::array<NonComparable, 0> a;
+
+  // Should still work because empty containers don't compare elements
+  VERIFY( t == a );
+  VERIFY( (t <=> a) == std::strong_ordering::equal );
+}
+
+int main()
+{
+  auto test_all = [] {
+    test01();
+    test02();
+  };
+
+  test_all();
+  static_VERIFY( test_all() );
+  return 0;
+}

Reply via email to