On Fri, Oct 17, 2025 at 6:00 PM Hewill Kang <[email protected]> wrote:

> Wow, I just noticed that the current wording allows tuple<> to be compared
> to any array<T, 0>, regardless of the type of T.
> However, tuple<T> can only be compared to array<T, 1> if T itself is
> comparable.
>
They common_reference is tuple<>, but they are not totally_ordered_with, as
array is not ordered.

> This seems to be a defect.
>
> Osama Abdelkader <[email protected]> 於 2025年10月17日 週五 下午11:27寫道:
>
>> Fixes #119721
>>
>> This fixes a C++23 compliance issue where std::tuple<> cannot be compared
>> with std::array<T, 0>. Both are empty tuple-like types and should be
>> comparable according to the C++23 standard.
>>
>> The fix adds the missing comparison operators:
>> - operator== and operator!= (return true and false respectively)
>> - operator<, operator<=, operator>, operator>= (follow ordering rules for
>> empty types)
>> - operator<=> (returns strong_ordering::equal)
>>
>> This resolves the 'rejects-valid' bug where GCC was rejecting valid C++23
>> code
>> that Clang with libc++ already supports correctly.
>>
>> libstdc++-v3/ChangeLog:
>>
>>         * include/std/tuple: Add comparison operators between tuple<> and
>> array<T, 0>.
>>
>> Signed-off-by: Osama Abdelkader <[email protected]>
>> ---
>>  libstdc++-v3/include/std/tuple | 88 ++++++++++++++++++++++++++++++++++
>>  1 file changed, 88 insertions(+)
>>
>> diff --git a/libstdc++-v3/include/std/tuple
>> b/libstdc++-v3/include/std/tuple
>> index 0ca616f1b..d3621dd16 100644
>> --- a/libstdc++-v3/include/std/tuple
>> +++ b/libstdc++-v3/include/std/tuple
>> @@ -1880,6 +1880,94 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>           using _Cat = typename
>> __tuple_like_common_comparison_category<_UTuple>::type;
>>           return std::__tuple_cmp<_Cat>(__t, __u,
>> index_sequence_for<_Elements...>());
>>         }
>> +
>> +  // Comparison operators between tuple<> and array<T, 0>
>> +  // These are needed because both are empty tuple-like types in C++23
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator==(const tuple<>&, const array<_Tp, 0>&)
>> +    { return true; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator==(const array<_Tp, 0>&, const tuple<>&)
>> +    { return true; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator!=(const tuple<>&, const array<_Tp, 0>&)
>> +    { return false; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator!=(const array<_Tp, 0>&, const tuple<>&)
>> +    { return false; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator<(const tuple<>&, const array<_Tp, 0>&)
>> +    { return false; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator<(const array<_Tp, 0>&, const tuple<>&)
>> +    { return false; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator<=(const tuple<>&, const array<_Tp, 0>&)
>> +    { return true; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator<=(const array<_Tp, 0>&, const tuple<>&)
>> +    { return true; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator>(const tuple<>&, const array<_Tp, 0>&)
>> +    { return false; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator>(const array<_Tp, 0>&, const tuple<>&)
>> +    { return false; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator>=(const tuple<>&, const array<_Tp, 0>&)
>> +    { return true; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr bool
>> +    operator>=(const array<_Tp, 0>&, const tuple<>&)
>> +    { return true; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr strong_ordering
>> +    operator<=>(const tuple<>&, const array<_Tp, 0>&)
>> +    { return strong_ordering::equal; }
>> +
>> +  template<typename _Tp>
>> +    [[nodiscard]]
>> +    constexpr strong_ordering
>> +    operator<=>(const array<_Tp, 0>&, const tuple<>&)
>> +    { return strong_ordering::equal; }
>> +
>>  #endif // C++23
>>
>>  #else // ! (concepts && consteval)
>> --
>> 2.43.0
>>
>>

Reply via email to