On Fri, Oct 17, 2025 at 6:33 PM Tomasz Kaminski <[email protected]> wrote:

>
>
> On Fri, Oct 17, 2025 at 6:27 PM Hewill Kang <[email protected]> wrote:
>
>> I'm not sure what you mean, but it does weird to me that the underlying
>> types can't be compared, but the corresponding tuple-like can be compared:
>>
>> #include <tuple>
>> #include <array>
>>
>> struct S {
>> void operator== (const S&) const = delete;
>> void operator<=>(const S&) const = delete;
>> void operator <(const S&) const = delete;
>> };
>>
>> int main() {
>> std::tuple<> t;
>> std::array<S, 0> a;
>> // a == a; // error
>> t < a; // ok
>>
> Yes, because the < is doing more efficient implementation of:
>        t < std::tuple<>(a);
>
And this constructor alos does not look on a, and it can be non-movable.
I think this is more a problem of array<S, 0> not being comparable, despite
being copyable regardless of S.

>
>
>> t == a; // ok
>> t <=> a; // ok
>> }
>>
>> Tomasz Kaminski <[email protected]> 於 2025年10月18日 週六 上午12:20寫道:
>>
>>>
>>>
>>> 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