From: Osama Abdelkader <[email protected]>
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: Tomasz Kamiński <[email protected]>
Signed-off-by: Osama Abdelkader <[email protected]>
---
v6:
- updates commit description
- uses VERIFY macro in tests
libstdc++-v3/include/std/tuple | 19 ++++++
.../tuple/comparison_operators/119721.cc | 65 +++++++++++++++++++
2 files changed, 84 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 0ca616f1b4f..b287694ccdb 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 00000000000..cd7d86da698
--- /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;
+}
--
2.51.0