On Mon, 20 Oct 2025 at 16:58, Tomasz Kamiński <[email protected]> wrote:
>
> 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.

I don't think we need the "Note: ..." part here, which basically just
tells us that yes, this code is correct. We should assume that all
code in our headers is correct or it wouldn't be there! :-)

The commit message already has that information, and this is just
implementing a direct requirement of the C++ standard, so we don't
need to justify it here.

So just leavethe first line, and remove the next three lines.

OK for trunk with that change, thanks!


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

Reply via email to