[PATCH] libstdc++: Add comparison operators between tuple<> and array<T, 0>
Tomasz Kaminski
tkaminsk@redhat.com
Fri Oct 17 16:34:41 GMT 2025
On Fri, Oct 17, 2025 at 6:33 PM Tomasz Kaminski <tkaminsk@redhat.com> wrote:
>
>
> On Fri, Oct 17, 2025 at 6:27 PM Hewill Kang <hewillk@gmail.com> 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 <tkaminsk@redhat.com> 於 2025年10月18日 週六 上午12:20寫道:
>>
>>>
>>>
>>> On Fri, Oct 17, 2025 at 6:00 PM Hewill Kang <hewillk@gmail.com> 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 <osama.abdelkader@gmail.com> 於 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 <osama.abdelkader@gmail.com>
>>>>> ---
>>>>> 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
>>>>>
>>>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20251017/64a70024/attachment-0001.htm>
More information about the Libstdc++
mailing list