diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -35,7 +35,7 @@ | `[stacktrace.basic.cmp] `_,| basic_stacktrace,[alg.three.way],Unassigned,|Not Started| | `[string.cmp] `_,| `basic_string `_,None,Mark de Wever,|Complete| | `[string.view.comparison] `_,| `basic_string_view `_,None,Mark de Wever,|Complete| -| `[array.syn] `_ (`general `_),| array,[expos.only.func],Unassigned,|Not Started| +| `[array.syn] `_ (`general `_),| `array `_,[expos.only.func],Adrian Vogelsgesang,|Complete| | `[deque.syn] `_ (`general `_),| deque,[expos.only.func],Unassigned,|Not Started| | `[forward.list.syn] `_ (`general `_),| forward_list,[expos.only.func],Unassigned,|Not Started| | `[list.syn] `_ (`general `_),| list,[expos.only.func],Unassigned,|Not Started| diff --git a/libcxx/include/array b/libcxx/include/array --- a/libcxx/include/array +++ b/libcxx/include/array @@ -77,15 +77,18 @@ template bool operator==(const array& x, const array& y); // constexpr in C++20 template - bool operator!=(const array& x, const array& y); // constexpr in C++20 + bool operator!=(const array& x, const array& y); // removed in C++20 template - bool operator<(const array& x, const array& y); // constexpr in C++20 + bool operator<(const array& x, const array& y); // removed in C++20 template - bool operator>(const array& x, const array& y); // constexpr in C++20 + bool operator>(const array& x, const array& y); // removed in C++20 template - bool operator<=(const array& x, const array& y); // constexpr in C++20 + bool operator<=(const array& x, const array& y); // removed in C++20 template - bool operator>=(const array& x, const array& y); // constexpr in C++20 + bool operator>=(const array& x, const array& y); // removed in C++20 +template + constexpr synth-three-way-result + operator<=>(const array& x, const array& y); // since C++23 template void swap(array& x, array& y) noexcept(noexcept(x.swap(y))); // constexpr in C++20 @@ -111,6 +114,7 @@ #include <__algorithm/equal.h> #include <__algorithm/fill_n.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/swap_ranges.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> @@ -395,18 +399,18 @@ return _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) +bool operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) +bool operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); @@ -414,28 +418,38 @@ template inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) +bool operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) +bool operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) +bool operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return !(__x < __y); } +#else // _LIBCPP_STD_VER > 17 + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr __synth_three_way_result<_Tp> +operator<=>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) +{ + return _VSTD::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), __synth_three_way); +} + +#endif // _LIBCPP_STD_VER > 17 + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<_Size == 0 || __is_swappable<_Tp>::value, void> diff --git a/libcxx/test/std/containers/sequences/array/compare.pass.cpp b/libcxx/test/std/containers/sequences/array/compare.pass.cpp --- a/libcxx/test/std/containers/sequences/array/compare.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/compare.pass.cpp @@ -24,47 +24,91 @@ TEST_CONSTEXPR_CXX20 bool tests() { - { - typedef std::array C; - const C c1 = {1, 2, 3}; - const C c2 = {1, 2, 3}; - const C c3 = {3, 2, 1}; - const C c4 = {1, 2, 1}; - assert(testComparisons(c1, c2, true, false)); - assert(testComparisons(c1, c3, false, true)); - assert(testComparisons(c1, c4, false, false)); - } - { - typedef std::array C; - const C c1 = {}; - const C c2 = {}; - assert(testComparisons(c1, c2, true, false)); - } - { - typedef std::array C; - const C c1 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)}; - const C c2 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)}; - const C c3 = {LessAndEqComp(3), LessAndEqComp(2), LessAndEqComp(1)}; - const C c4 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)}; - assert(testComparisons(c1, c2, true, false)); - assert(testComparisons(c1, c3, false, true)); - assert(testComparisons(c1, c4, false, false)); - } - { - typedef std::array C; - const C c1 = {}; - const C c2 = {}; - assert(testComparisons(c1, c2, true, false)); - } + // Arrays where the elements support all comparison operators + { + typedef std::array C; + const C c1 = {1, 2, 3}; + const C c2 = {1, 2, 3}; + const C c3 = {3, 2, 1}; + const C c4 = {1, 2, 1}; + assert(testComparisons(c1, c2, true, false)); + assert(testComparisons(c1, c3, false, true)); + assert(testComparisons(c1, c4, false, false)); +#if TEST_STD_VER >= 20 + assert(testOrder(c1, c2, std::strong_ordering::equal)); + assert(testOrder(c1, c3, std::strong_ordering::less)); + assert(testOrder(c1, c4, std::strong_ordering::greater)); +#endif + } + // Empty array + { + typedef std::array C; + const C c1 = {}; + const C c2 = {}; + assert(testComparisons(c1, c2, true, false)); +#if TEST_STD_VER >= 20 + assert(testOrder(c1, c2, std::strong_ordering::equal)); +#endif + } + // Arrays where the elements support only less and equality comparisons + { + typedef std::array C; + const C c1 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)}; + const C c2 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)}; + const C c3 = {LessAndEqComp(3), LessAndEqComp(2), LessAndEqComp(1)}; + const C c4 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)}; + assert(testComparisons(c1, c2, true, false)); + assert(testComparisons(c1, c3, false, true)); + assert(testComparisons(c1, c4, false, false)); +#if TEST_STD_VER >= 20 + assert(testOrder(c1, c2, std::strong_ordering::equal)); + assert(testOrder(c1, c3, std::strong_ordering::less)); + assert(testOrder(c1, c4, std::strong_ordering::greater)); +#endif + } + // Empty array where the elements support only less and equality comparisons + { + typedef std::array C; + const C c1 = {}; + const C c2 = {}; + assert(testComparisons(c1, c2, true, false)); +#if TEST_STD_VER >= 20 + assert(testOrder(c1, c2, std::strong_ordering::equal)); +#endif + } +#if TEST_STD_VER >= 20 + // Arrays with weakly comparable elements + { + typedef std::array C; + const C c1 = {1, 2, 3}; + const C c2 = {1, 2, 3}; + const C c3 = {3, 2, 1}; + const C c4 = {1, 2, 1}; + assert(testOrder(c1, c2, std::weak_ordering::equivalent)); + assert(testOrder(c1, c3, std::weak_ordering::less)); + assert(testOrder(c1, c4, std::weak_ordering::greater)); + } + // Arrays with partially comparable elements + { + typedef std::array C; + const C c1 = {1, 2, 3}; + const C c2 = {1, 2, 3}; + const C c3 = {3, 2, 1}; + const C c4 = {1, 2, 1}; + assert(testOrder(c1, c2, std::weak_ordering::equivalent)); + assert(testOrder(c1, c3, std::weak_ordering::less)); + assert(testOrder(c1, c4, std::weak_ordering::greater)); + } +#endif - return true; + return true; } int main(int, char**) { tests(); #if TEST_STD_VER >= 20 - static_assert(tests(), ""); + static_assert(tests()); #endif return 0; }