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 @@ -39,7 +39,8 @@ | `[deque.syn] `_ (`general `_),| `deque `_,[expos.only.func],Hristo Hristov,|Complete| | `[forward.list.syn] `_ (`general `_),| `forward_list `_,[expos.only.func],Hristo Hristov,|Complete| | `[list.syn] `_ (`general `_),| `list `_,[expos.only.func],Adrian Vogelsgesang,|Complete| -| `[vector.syn] `_ (`general `_),| `vector `_,[expos.only.func],Adrian Vogelsgesang,|In Progress| +| `[vector.syn] `_ (`general `_),| `vector `_,[expos.only.func],"| Adrian Vogelsgesang +| Hristo Hristov",|Complete| | `[associative.map.syn] `_ (`general `_),"| `map `_ | `multimap `_",[expos.only.func],Hristo Hristov,|Complete| | `[associative.set.syn] `_ (`general `_),"| multiset diff --git a/libcxx/include/__algorithm/lexicographical_compare_three_way.h b/libcxx/include/__algorithm/lexicographical_compare_three_way.h --- a/libcxx/include/__algorithm/lexicographical_compare_three_way.h +++ b/libcxx/include/__algorithm/lexicographical_compare_three_way.h @@ -97,13 +97,13 @@ "The comparator passed to lexicographical_compare_three_way must return a comparison category type."); static_assert(std::is_copy_constructible_v<_InputIterator1>, "Iterators must be copy constructible."); static_assert(std::is_copy_constructible_v<_InputIterator2>, "Iterators must be copy constructible."); - __three_way_comp_ref_type<_Cmp> __wrapped_comp_ref(__comp); if constexpr (__is_cpp17_random_access_iterator<_InputIterator1>::value && __is_cpp17_random_access_iterator<_InputIterator2>::value) { return std::__lexicographical_compare_three_way_fast_path( - std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __wrapped_comp_ref); + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __comp); } else { // Unoptimized implementation which compares the iterators against the end in every loop iteration + __three_way_comp_ref_type<_Cmp> __wrapped_comp_ref(__comp); return std::__lexicographical_compare_three_way_slow_path( std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __wrapped_comp_ref); } diff --git a/libcxx/include/vector b/libcxx/include/vector --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -249,12 +249,15 @@ template struct hash>; -template bool operator==(const vector& x, const vector& y); -template bool operator< (const vector& x, const vector& y); -template bool operator!=(const vector& x, const vector& y); -template bool operator> (const vector& x, const vector& y); -template bool operator>=(const vector& x, const vector& y); -template bool operator<=(const vector& x, const vector& y); +template bool operator==(const vector& x, const vector& y); // constexpr since C++20 +template bool operator!=(const vector& x, const vector& y); // removed in C++20 +template bool operator< (const vector& x, const vector& y); // removed in C++20 +template bool operator> (const vector& x, const vector& y); // removed in C++20 +template bool operator>=(const vector& x, const vector& y); // removed in C++20 +template bool operator<=(const vector& x, const vector& y); // removed in C++20 +template constexpr + constexpr synth-three-way-result operator<=>(const vector& x, + const vector& y); // since C++20 template void swap(vector& x, vector& y) @@ -262,10 +265,10 @@ template typename vector::size_type -erase(vector& c, const U& value); // C++20 +erase(vector& c, const U& value); // since C++20 template typename vector::size_type -erase_if(vector& c, Predicate pred); // C++20 +erase_if(vector& c, Predicate pred); // since C++20 template @@ -282,6 +285,7 @@ #include <__algorithm/equal.h> #include <__algorithm/fill_n.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/remove.h> #include <__algorithm/remove_if.h> #include <__algorithm/rotate.h> @@ -3240,8 +3244,9 @@ return __sz == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3250,7 +3255,6 @@ } template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3259,7 +3263,6 @@ } template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3268,7 +3271,6 @@ } template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3277,7 +3279,6 @@ } template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3285,6 +3286,17 @@ return !(__y < __x); } +#else // _LIBCPP_STD_VER >= 20 + +template +inline _LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp> +operator<=>(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>); +} + +#endif // _LIBCPP_STD_VER <= 17 + template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI diff --git a/libcxx/test/std/containers/sequences/vector.bool/compare.three_way.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/compare.three_way.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/compare.three_way.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template +// constexpr synth-three-way-result operator<=>(const vector& x, +// const vector& y); + +#include +#include + +#include "test_comparisons.h" + +constexpr bool test_sequence_container_spaceship_vectorbool() { + // Empty containers + { + std::vector l1; + std::vector l2; + assert(testOrder(l1, l2, std::strong_ordering::equivalent)); + } + // Identical contents + { + std::vector t1{true, true}; + std::vector t2{true, true}; + assert(testOrder(t1, t2, std::strong_ordering::equivalent)); + std::vector f1{false, false}; + std::vector f2{false, false}; + assert(testOrder(f1, f2, std::strong_ordering::equivalent)); + } + // Less, due to contained values + { + std::vector l1{true, false}; + std::vector l2{true, true}; + assert(testOrder(l1, l2, std::strong_ordering::less)); + } + // Greater, due to contained values + { + std::vector l1{true, true}; + std::vector l2{true, false}; + assert(testOrder(l1, l2, std::strong_ordering::greater)); + } + // Shorter list + { + std::vector l1{true}; + std::vector l2{true, true}; + assert(testOrder(l1, l2, std::strong_ordering::less)); + std::vector t1{true}; + std::vector t2{true, true}; + assert(testOrder(t1, t2, std::strong_ordering::less)); + std::vector f1{false}; + std::vector f2{false, false}; + assert(testOrder(f1, f2, std::strong_ordering::less)); + } + // Longer list + { + std::vector l1{true, false}; + std::vector l2{true}; + assert(testOrder(l1, l2, std::strong_ordering::greater)); + std::vector t1{true, true}; + std::vector t2{true}; + assert(testOrder(t1, t2, std::strong_ordering::greater)); + std::vector f1{false, false}; + std::vector f2{false}; + assert(testOrder(f1, f2, std::strong_ordering::greater)); + } + + return true; +} + +int main(int, char**) { + assert(test_sequence_container_spaceship_vectorbool()); + static_assert(test_sequence_container_spaceship_vectorbool()); + return 0; +} diff --git a/libcxx/test/std/containers/sequences/vector/compare.three_way.pass.cpp b/libcxx/test/std/containers/sequences/vector/compare.three_way.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector/compare.three_way.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template +// constexpr synth-three-way-result operator<=>(const vector& x, +// const vector& y); + +#include +#include + +#include "test_container_comparisons.h" + +int main(int, char**) { + assert(test_sequence_container_spaceship()); + static_assert(test_sequence_container_spaceship()); + return 0; +}