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