diff --git a/libcxx/include/__algorithm/ranges_unique.h b/libcxx/include/__algorithm/ranges_unique.h index a817359abd889..64191e3c94674 100644 --- a/libcxx/include/__algorithm/ranges_unique.h +++ b/libcxx/include/__algorithm/ranges_unique.h @@ -47,8 +47,8 @@ struct __unique { indirect_equivalence_relation> _Comp = ranges::equal_to> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = - std::__unique<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + auto __ret = std::__unique_sorted_range<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); return {std::move(__ret.first), std::move(__ret.second)}; } @@ -58,7 +58,7 @@ struct __unique { requires permutable> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__unique<_RangeAlgPolicy>( + auto __ret = std::__unique_sorted_range<_RangeAlgPolicy>( ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); return {std::move(__ret.first), std::move(__ret.second)}; } diff --git a/libcxx/include/__algorithm/unique.h b/libcxx/include/__algorithm/unique.h index 307c424a7c2fb..4aa14fbc92e96 100644 --- a/libcxx/include/__algorithm/unique.h +++ b/libcxx/include/__algorithm/unique.h @@ -29,9 +29,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD // unique +// For this unchecked algorithm, __pred does not need to be an equivalence relation. template [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_Iter, _Iter> -__unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { +__unique_sorted_range(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { __identity __proj; __first = std::__adjacent_find(__first, __last, __pred, __proj); if (__first != __last) { @@ -50,7 +51,7 @@ __unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { template [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { - return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first; + return std::__unique_sorted_range<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first; } template diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h index 50487cada24c0..d0d83fecf3fe4 100644 --- a/libcxx/include/__flat_map/flat_map.h +++ b/libcxx/include/__flat_map/flat_map.h @@ -10,6 +10,7 @@ #ifndef _LIBCPP___FLAT_MAP_FLAT_MAP_H #define _LIBCPP___FLAT_MAP_FLAT_MAP_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/lower_bound.h> #include <__algorithm/min.h> @@ -17,8 +18,8 @@ #include <__algorithm/ranges_equal.h> #include <__algorithm/ranges_inplace_merge.h> #include <__algorithm/ranges_sort.h> -#include <__algorithm/ranges_unique.h> #include <__algorithm/remove_if.h> +#include <__algorithm/unique.h> #include <__algorithm/upper_bound.h> #include <__assert> #include <__compare/synth_three_way.h> @@ -944,7 +945,8 @@ class flat_map { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __sort_and_unique() { auto __zv = ranges::views::zip(__containers_.keys, __containers_.values); ranges::sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); }); - auto __dup_start = ranges::unique(__zv, __key_equiv(__compare_)).begin(); + auto __dup_start = + std::__unique_sorted_range<_RangeAlgPolicy>(__zv.begin(), __zv.end(), __key_not_less(__compare_)).first; auto __dist = ranges::distance(__zv.begin(), __dup_start); __containers_.keys.erase(__containers_.keys.begin() + __dist, __containers_.keys.end()); __containers_.values.erase(__containers_.values.begin() + __dist, __containers_.values.end()); @@ -979,7 +981,8 @@ class flat_map { } ranges::inplace_merge(__zv.begin(), __zv.begin() + __append_start_offset, __end, __compare_key); - auto __dup_start = ranges::unique(__zv, __key_equiv(__compare_)).begin(); + auto __dup_start = + std::__unique_sorted_range<_RangeAlgPolicy>(__zv.begin(), __zv.end(), __key_not_less(__compare_)).first; auto __dist = ranges::distance(__zv.begin(), __dup_start); __containers_.keys.erase(__containers_.keys.begin() + __dist, __containers_.keys.end()); __containers_.values.erase(__containers_.values.begin() + __dist, __containers_.values.end()); @@ -1135,11 +1138,11 @@ class flat_map { containers __containers_; _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; - struct __key_equiv { - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool - operator()(const_reference __x, const_reference __y) const { - return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x)); + struct __key_not_less { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_not_less(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const auto& __x, const auto& __y) const { + // __x is less or equal to __y because the range is already sorted + return !__comp_(std::get<0>(__x), std::get<0>(__y)); } key_compare __comp_; }; diff --git a/libcxx/include/__flat_set/flat_set.h b/libcxx/include/__flat_set/flat_set.h index 57c3926e33b68..d97b66e1cdf5d 100644 --- a/libcxx/include/__flat_set/flat_set.h +++ b/libcxx/include/__flat_set/flat_set.h @@ -10,14 +10,15 @@ #ifndef _LIBCPP___FLAT_SET_FLAT_SET_H #define _LIBCPP___FLAT_SET_FLAT_SET_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/lower_bound.h> #include <__algorithm/ranges_adjacent_find.h> #include <__algorithm/ranges_equal.h> #include <__algorithm/ranges_inplace_merge.h> #include <__algorithm/ranges_sort.h> -#include <__algorithm/ranges_unique.h> #include <__algorithm/remove_if.h> +#include <__algorithm/unique.h> #include <__algorithm/upper_bound.h> #include <__assert> #include <__compare/synth_three_way.h> @@ -688,7 +689,8 @@ class flat_set { // is no invariant state to preserve _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __sort_and_unique() { ranges::sort(__keys_, __compare_); - auto __dup_start = ranges::unique(__keys_, __key_equiv(__compare_)).begin(); + auto __dup_start = + std::__unique_sorted_range<_RangeAlgPolicy>(__keys_.begin(), __keys_.end(), __key_not_less(__compare_)).first; __keys_.erase(__dup_start, __keys_.end()); } @@ -706,7 +708,8 @@ class flat_set { } ranges::inplace_merge(__keys_.begin(), __keys_.begin() + __old_size, __keys_.end(), __compare_); - auto __dup_start = ranges::unique(__keys_, __key_equiv(__compare_)).begin(); + auto __dup_start = + std::__unique_sorted_range<_RangeAlgPolicy>(__keys_.begin(), __keys_.end(), __key_not_less(__compare_)).first; __keys_.erase(__dup_start, __keys_.end()); } __on_failure.__complete(); @@ -781,11 +784,11 @@ class flat_set { _KeyContainer __keys_; _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; - struct __key_equiv { - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool - operator()(const_reference __x, const_reference __y) const { - return !__comp_(__x, __y) && !__comp_(__y, __x); + struct __key_not_less { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_not_less(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const auto& __x, const auto& __y) const { + // __x is less or equal to __y because the range is already sorted + return !__comp_(__x, __y); } key_compare __comp_; };