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.

libstdc++-v3/ChangeLog:

        PR libstdc++/119721
        * include/std/tuple: Add tuple<> comparison operators for
        empty tuple-like types.
        * testsuite/23_containers/tuple/comparison_operators/119721.cc: New 
test.

Signed-off-by: Osama Abdelkader <[email protected]>
---
v5:
- made the operators hidden friends 
v4:
- Added testsuite test
v3:
- Added noexcept specifiers to the operators
v2:
- Replaced explicit array<T, 0> operators with generic tuple-like operators
- Only operator== and operator<=> are provided
- Operators work with any empty tuple-like type
- No need for reversed argument order
---
 libstdc++-v3/include/std/tuple                | 19 +++++
 .../tuple/comparison_operators/119721.cc      | 71 +++++++++++++++++++
 2 files changed, 90 insertions(+)
 create mode 100644 
libstdc++-v3/testsuite/23_containers/tuple/comparison_operators/119721.cc

diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 0ca616f1b..b287694cc 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -1999,6 +1999,25 @@ _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
+      // Note: These operators allow comparison with any empty tuple-like type,
+      // including array<T, 0>, where T may not be comparable.
+      // This is correct because empty tuple-like types don't compare elements.
+      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 000000000..711874acf
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/tuple/comparison_operators/119721.cc
@@ -0,0 +1,71 @@
+// { 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 <cassert>
+
+void test01()
+{
+    std::tuple<> t;
+    std::array<int, 0> a;
+
+    // Basic comparison should work
+    assert(t == a);
+    assert(a == t);
+    assert(!(t != a));
+    assert(!(a != t));
+
+    // Ordering comparisons should be equal
+    assert(!(t < a));
+    assert(!(t > a));
+    assert(t <= a);
+    assert(t >= a);
+    assert(!(a < t));
+    assert(!(a > t));
+    assert(a <= t);
+    assert(a >= t);
+
+    // Three-way comparison should return equal
+    assert((t <=> a) == std::strong_ordering::equal);
+    assert((a <=> t) == std::strong_ordering::equal);
+}
+
+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
+    assert(t == a);
+    assert((t <=> a) == std::strong_ordering::equal);
+}
+
+void test03()
+{
+    // Test constexpr evaluation
+    constexpr std::tuple<> t;
+    constexpr std::array<int, 0> a;
+
+    constexpr bool eq = t == a;
+    constexpr auto cmp = t <=> a;
+
+    static_assert(eq == true);
+    static_assert(cmp == std::strong_ordering::equal);
+}
+
+int main()
+{
+    test01();
+    test02();
+    test03();
+    return 0;
+}
-- 
2.43.0

Reply via email to