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; +}
