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