From: Patrick Palka Date: Thu, 13 Feb 2020 17:17:01 +0000 (-0500) Subject: libstdc++: Convert the ranges algorithm entities into function objects X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b40c57bdd2ea2e171657e2bfbb7702171f4c9040;p=gcc.git libstdc++: Convert the ranges algorithm entities into function objects This is the standard way to inhibit ADL for these entities, which is required as per [algorithms.requirements] p2 and [specialized.algorithms] p4. The conversion was done mostly mechanically with a custom Vim macro. libstdc++-v3/ChangeLog: * include/bits/ranges_algo.h: (adjacent_find, all_of, any_of, binary_search, copy_if, count, count_if, equal_range, find, find_end, find_first_of, find_if, find_if_not, for_each, generate, generate_n, includes, inplace_merge, is_heap, is_heap_until, is_partitioned, is_permutation, is_sorted, is_sorted_until, lexicographical_compare, lower_bound, make_heap, max, max_element, merge, min, min_element, minmax, minmax_element, mismatch, next_permutation, none_of, nth_element, partial_sort, partial_sort_copy, partition, partition_copy, partition_point, pop_heap, prev_permutation, push_heap, remove, remove_copy, remove_copy_if, remove_if, replace, replace_copy, replace_copy_if, replace_if, reverse, reverse_copy, rotate, rotate_copy, search, search_n, set_difference, set_intersection, set_symmetric_difference, set_union, shuffle, sort, sort_heap, stable_partition, stable_sort, swap_ranges, transform, unique, unique_copy, upper_bound): Convert into function objects. * include/bits/ranges_algobase.h: (equal, copy, move, copy_n, fill_n, fill, move_backward, copy_backward): Likewise. * include/bits/ranges_uninitialized.h (uninitialized_default_construct, uninitialized_default_construct_n, uninitialized_value_construct, uninitialized_value_construct_n, uninitialized_copy, uninitialized_copy_n, uninitialized_move, uninitialized_move_n, uninitialized_fill, uninitialized_fill_n, construct_at, destroy_at, destroy, destroy_n): Likewise. --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 624c0c2f7c9..cdb70789412 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,29 @@ 2020-02-15 Patrick Palka + * include/bits/ranges_algo.h: (adjacent_find, all_of, any_of, + binary_search, copy_if, count, count_if, equal_range, find, find_end, + find_first_of, find_if, find_if_not, for_each, generate, generate_n, + includes, inplace_merge, is_heap, is_heap_until, is_partitioned, + is_permutation, is_sorted, is_sorted_until, lexicographical_compare, + lower_bound, make_heap, max, max_element, merge, min, min_element, + minmax, minmax_element, mismatch, next_permutation, none_of, + nth_element, partial_sort, partial_sort_copy, partition, partition_copy, + partition_point, pop_heap, prev_permutation, push_heap, remove, + remove_copy, remove_copy_if, remove_if, replace, replace_copy, + replace_copy_if, replace_if, reverse, reverse_copy, rotate, rotate_copy, + search, search_n, set_difference, set_intersection, + set_symmetric_difference, set_union, shuffle, sort, sort_heap, + stable_partition, stable_sort, swap_ranges, transform, unique, + unique_copy, upper_bound): Convert into function objects. + * include/bits/ranges_algobase.h: (equal, copy, move, copy_n, fill_n, + fill, move_backward, copy_backward): Likewise. + * include/bits/ranges_uninitialized.h (uninitialized_default_construct, + uninitialized_default_construct_n, uninitialized_value_construct, + uninitialized_value_construct_n, uninitialized_copy, + uninitialized_copy_n, uninitialized_move, uninitialized_move_n, + uninitialized_fill, uninitialized_fill_n, construct_at, destroy_at, + destroy, destroy_n): Likewise. + * include/bits/ranges_algo.h (ranges::__find_end): Fold into ... (ranges::find_end): ... here. (ranges::__lexicographical_compare): Fold into ... diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index 6b6f4defdf5..af6d1722998 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -67,68 +67,83 @@ namespace ranges } } // namespace __detail - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr bool - all_of(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - for (; __first != __last; ++__first) - if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - return false; - return true; - } + struct __all_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } - template, _Proj>> _Pred> - constexpr bool - all_of(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::all_of(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr bool - any_of(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - return true; - return false; - } + template, _Proj>> _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; - template, _Proj>> _Pred> - constexpr bool - any_of(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::any_of(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr bool - none_of(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - return false; - return true; - } + inline constexpr __all_of_fn all_of{}; - template, _Proj>> _Pred> - constexpr bool - none_of(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::none_of(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } + struct __any_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return true; + return false; + } + + template, _Proj>> _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __any_of_fn any_of{}; + + struct __none_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __none_of_fn none_of{}; template struct for_each_result @@ -148,177 +163,212 @@ namespace ranges { return {std::move(in), std::move(fun)}; } }; - template _Sent, - typename _Proj = identity, - indirectly_unary_invocable> _Fun> - constexpr for_each_result<_Iter, _Fun> - for_each(_Iter __first, _Sent __last, _Fun __f, _Proj __proj = {}) - { - for (; __first != __last; ++__first) - std::__invoke(__f, std::__invoke(__proj, *__first)); - return { std::move(__first), std::move(__f) }; - } - - template, _Proj>> - _Fun> - constexpr for_each_result, _Fun> - for_each(_Range&& __r, _Fun __f, _Proj __proj = {}) - { - return ranges::for_each(ranges::begin(__r), ranges::end(__r), - std::move(__f), std::move(__proj)); - } - - template _Sent, typename _Tp, - typename _Proj = identity> - requires indirect_binary_predicate, const _Tp*> - constexpr _Iter - find(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) - { - while (__first != __last - && !(std::__invoke(__proj, *__first) == __value)) - ++__first; - return __first; - } - - template - requires indirect_binary_predicate, _Proj>, - const _Tp*> - constexpr safe_iterator_t<_Range> - find(_Range&& __r, const _Tp& __value, _Proj __proj = {}) - { - return ranges::find(ranges::begin(__r), ranges::end(__r), __value, - std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr _Iter - find_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - while (__first != __last - && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - ++__first; - return __first; - } - - template, _Proj>> - _Pred> - constexpr safe_iterator_t<_Range> - find_if(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::find_if(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr _Iter - find_if_not(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - while (__first != __last - && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - ++__first; - return __first; - } - - template, _Proj>> - _Pred> - constexpr safe_iterator_t<_Range> - find_if_not(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::find_if_not(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr _Iter1 - find_first_of(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - for (; __first1 != __last1; ++__first1) - for (auto __iter = __first2; __iter != __last2; ++__iter) - if (std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__iter))) - return __first1; - return __first1; - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr safe_iterator_t<_Range1> - find_first_of(_Range1&& __r1, _Range2&& __r2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::find_first_of(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } - - template _Sent, - typename _Tp, typename _Proj = identity> - requires indirect_binary_predicate, - const _Tp*> - constexpr iter_difference_t<_Iter> - count(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) - { - iter_difference_t<_Iter> __n = 0; - for (; __first != __last; ++__first) - if (std::__invoke(__proj, *__first) == __value) - ++__n; - return __n; - } - - template - requires indirect_binary_predicate, _Proj>, - const _Tp*> - constexpr range_difference_t<_Range> - count(_Range&& __r, const _Tp& __value, _Proj __proj = {}) - { - return ranges::count(ranges::begin(__r), ranges::end(__r), - __value, std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr iter_difference_t<_Iter> - count_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - iter_difference_t<_Iter> __n = 0; - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - ++__n; - return __n; - } - - template, _Proj>> _Pred> - constexpr range_difference_t<_Range> - count_if(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::count_if(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } + struct __for_each_fn + { + template _Sent, + typename _Proj = identity, + indirectly_unary_invocable> _Fun> + constexpr for_each_result<_Iter, _Fun> + operator()(_Iter __first, _Sent __last, _Fun __f, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + std::__invoke(__f, std::__invoke(__proj, *__first)); + return { std::move(__first), std::move(__f) }; + } + + template, _Proj>> + _Fun> + constexpr for_each_result, _Fun> + operator()(_Range&& __r, _Fun __f, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__f), std::move(__proj)); + } + }; + + inline constexpr __for_each_fn for_each{}; + + struct __find_fn + { + template _Sent, typename _Tp, + typename _Proj = identity> + requires indirect_binary_predicate, const _Tp*> + constexpr _Iter + operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const + { + while (__first != __last + && !(std::__invoke(__proj, *__first) == __value)) + ++__first; + return __first; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), __value, + std::move(__proj)); + } + }; + + inline constexpr __find_fn find{}; + + struct __find_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + while (__first != __last + && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __find_if_fn find_if{}; + + struct __find_if_not_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + while (__first != __last + && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __find_if_not_fn find_if_not{}; + + struct __find_first_of_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr _Iter1 + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + for (; __first1 != __last1; ++__first1) + for (auto __iter = __first2; __iter != __last2; ++__iter) + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__iter))) + return __first1; + return __first1; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr safe_iterator_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __find_first_of_fn find_first_of{}; + + struct __count_fn + { + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __value) + ++__n; + return __n; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr range_difference_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __count_fn count{}; + + struct __count_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__n; + return __n; + } + + template, _Proj>> _Pred> + constexpr range_difference_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __count_if_fn count_if{}; template struct mismatch_result @@ -339,457 +389,467 @@ namespace ranges { return {std::move(in1), std::move(in2)}; } }; - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr mismatch_result<_Iter1, _Iter2> - mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - while (__first1 != __last1 && __first2 != __last2 - && (bool)std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - { - ++__first1; - ++__first2; - } - return { std::move(__first1), std::move(__first2) }; - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr mismatch_result, iterator_t<_Range2>> - mismatch(_Range1&& __r1, _Range2&& __r2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::mismatch(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } - - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr subrange<_Iter1> - search(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - if (__first1 == __last1 || __first2 == __last2) - return {__first1, __first1}; - - for (;;) - { - for (;;) - { - if (__first1 == __last1) - return {__first1, __first1}; - if (std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - break; - ++__first1; - } - auto __cur1 = __first1; - auto __cur2 = __first2; - for (;;) - { - if (++__cur2 == __last2) - return {__first1, ++__cur1}; - if (++__cur1 == __last1) - return {__cur1, __cur1}; - if (!(bool)std::__invoke(__pred, - std::__invoke(__proj1, *__cur1), - std::__invoke(__proj2, *__cur2))) - { - ++__first1; - break; - } - } - } - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr safe_subrange_t<_Range1> - search(_Range1&& __r1, _Range2&& __r2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::search(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } - - template _Sent, typename _Tp, - typename _Pred = ranges::equal_to, typename _Proj = identity> - requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj> - constexpr subrange<_Iter> - search_n(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, - const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) - { - if (__count <= 0) - return {__first, __first}; - - auto __value_comp = [&] (_Rp&& __arg) { - return std::__invoke(__pred, std::forward<_Rp>(__arg), __value); - }; - if (__count == 1) + struct __mismatch_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr mismatch_result<_Iter1, _Iter2> + operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2 + && (bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) { - __first = ranges::find_if(std::move(__first), __last, - std::move(__value_comp), std::move(__proj)); - if (__first == __last) - return {__first, __first}; - else - { - auto __end = __first; - return {__first, ++__end}; - } + ++__first1; + ++__first2; } + return { std::move(__first1), std::move(__first2) }; + } - if constexpr (sized_sentinel_for<_Sent, _Iter>) - { - auto __tail_size = __last - __first; - auto __remainder = __count; - - while (__remainder <= __tail_size) - { - __first += __remainder; - __tail_size -= __remainder; - auto __backtrack = __first; - while (__value_comp(std::__invoke(__proj, *--__backtrack))) - { - if (--__remainder == 0) - return {__first - __count, __first}; - } - } - auto __i = __first + __tail_size; - return {__i, __i}; - } - else - { - __first = ranges::find_if(__first, __last, __value_comp, __proj); - while (__first != __last) - { - auto __n = __count; - auto __i = __first; - ++__i; - while (__i != __last && __n != 1 - && __value_comp(std::__invoke(__proj, *__i))) - { - ++__i; - --__n; - } - if (__n == 1) - return {__first, __i}; - if (__i == __last) - return {__i, __i}; - __first = ranges::find_if(++__i, __last, __value_comp, __proj); - } - return {__first, __first}; - } - } - - template - requires indirectly_comparable, const _Tp*, _Pred, _Proj> - constexpr safe_subrange_t<_Range> - search_n(_Range&& __r, range_difference_t<_Range> __count, - const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) - { - return ranges::search_n(ranges::begin(__r), ranges::end(__r), - std::move(__count), __value, - std::move(__pred), std::move(__proj)); - } + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr mismatch_result, iterator_t<_Range2>> + operator()(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + inline constexpr __mismatch_fn mismatch{}; + struct __search_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if (__first1 == __last1 || __first2 == __last2) + return {__first1, __first1}; - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr subrange<_Iter1> - find_end(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - if constexpr (bidirectional_iterator<_Iter1> - && bidirectional_iterator<_Iter2>) - { - auto __i1 = ranges::next(__first1, __last1); - auto __i2 = ranges::next(__first2, __last2); - auto __rresult - = ranges::search(reverse_iterator<_Iter1>{__i1}, - reverse_iterator<_Iter1>{__first1}, - reverse_iterator<_Iter2>{__i2}, - reverse_iterator<_Iter2>{__first2}, - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - auto __result_first = ranges::end(__rresult).base(); - auto __result_last = ranges::begin(__rresult).base(); - if (__result_last == __first1) - return {__i1, __i1}; - else - return {__result_first, __result_last}; - } - else - { - auto __i = ranges::next(__first1, __last1); - if (__first2 == __last2) - return {__i, __i}; + for (;;) + { + for (;;) + { + if (__first1 == __last1) + return {__first1, __first1}; + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + ++__first1; + } + auto __cur1 = __first1; + auto __cur2 = __first2; + for (;;) + { + if (++__cur2 == __last2) + return {__first1, ++__cur1}; + if (++__cur1 == __last1) + return {__cur1, __cur1}; + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__cur1), + std::__invoke(__proj2, *__cur2))) + { + ++__first1; + break; + } + } + } + } - auto __result_begin = __i; - auto __result_end = __i; - for (;;) - { - auto __new_range = ranges::search(__first1, __last1, - __first2, __last2, - __pred, __proj1, __proj2); - auto __new_result_begin = ranges::begin(__new_range); - auto __new_result_end = ranges::end(__new_range); - if (__new_result_begin == __last1) - return {__result_begin, __result_end}; - else - { - __result_begin = __new_result_begin; - __result_end = __new_result_end; - __first1 = __result_begin; - ++__first1; - } - } - } - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr safe_subrange_t<_Range1> - find_end(_Range1&& __r1, _Range2&& __r2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::find_end(ranges::begin(__r1), ranges::end(__r1), + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr safe_subrange_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2), std::move(__pred), std::move(__proj1), std::move(__proj2)); - } - - template _Sent, - typename _Proj = identity, - indirect_binary_predicate, - projected<_Iter, _Proj>> _Pred - = ranges::equal_to> - constexpr _Iter - adjacent_find(_Iter __first, _Sent __last, - _Pred __pred = {}, _Proj __proj = {}) - { - if (__first == __last) - return __first; - auto __next = __first; - for (; ++__next != __last; __first = __next) - { - if (std::__invoke(__pred, - std::__invoke(__proj, *__first), - std::__invoke(__proj, *__next))) - return __first; - } - return __next; - } - - template, _Proj>, - projected, _Proj>> _Pred = ranges::equal_to> - constexpr safe_iterator_t<_Range> - adjacent_find(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) - { - return ranges::adjacent_find(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Proj1 = identity, typename _Proj2 = identity, - indirect_equivalence_relation, - projected<_Iter2, _Proj2>> _Pred - = ranges::equal_to> - constexpr bool - is_permutation(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - constexpr bool __sized_iters - = (sized_sentinel_for<_Sent1, _Iter1> - && sized_sentinel_for<_Sent2, _Iter2>); - if constexpr (__sized_iters) - { - auto __d1 = ranges::distance(__first1, __last1); - auto __d2 = ranges::distance(__first2, __last2); - if (__d1 != __d2) - return false; - } + } + }; - // Efficiently compare identical prefixes: O(N) if sequences - // have the same elements in the same order. - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - if (!(bool)std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - break; + inline constexpr __search_fn search{}; - if constexpr (__sized_iters) - { - if (__first1 == __last1) - return true; - } - else - { - auto __d1 = ranges::distance(__first1, __last1); - auto __d2 = ranges::distance(__first2, __last2); - if (__d1 == 0 && __d2 == 0) - return true; - if (__d1 != __d2) - return false; - } + struct __search_n_fn + { + template _Sent, typename _Tp, + typename _Pred = ranges::equal_to, typename _Proj = identity> + requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const + { + if (__count <= 0) + return {__first, __first}; - for (auto __scan = __first1; __scan != __last1; ++__scan) - { - auto __proj_scan = std::__invoke(__proj1, *__scan); - auto __comp_scan = [&] (_Tp&& __arg) { - return std::__invoke(__pred, __proj_scan, - std::forward<_Tp>(__arg)); - }; - if (__scan != ranges::find_if(__first1, __scan, - __comp_scan, __proj1)) - continue; // We've seen this one before. - - auto __matches = ranges::count_if(__first2, __last2, - __comp_scan, __proj2); - if (__matches == 0 - || ranges::count_if(__scan, __last1, - __comp_scan, __proj1) != __matches) - return false; - } - return true; - } - - template, _Proj1>, - projected, _Proj2>> _Pred = ranges::equal_to> - constexpr bool - is_permutation(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::is_permutation(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } + auto __value_comp = [&] (_Rp&& __arg) { + return std::__invoke(__pred, std::forward<_Rp>(__arg), __value); + }; + if (__count == 1) + { + __first = ranges::find_if(std::move(__first), __last, + std::move(__value_comp), std::move(__proj)); + if (__first == __last) + return {__first, __first}; + else + { + auto __end = __first; + return {__first, ++__end}; + } + } - template - using copy_if_result = copy_result<_Iter, _Out>; + if constexpr (sized_sentinel_for<_Sent, _Iter>) + { + auto __tail_size = __last - __first; + auto __remainder = __count; - template _Sent, - weakly_incrementable _Out, typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_Iter, _Out> - constexpr copy_if_result<_Iter, _Out> - copy_if(_Iter __first, _Sent __last, _Out __result, - _Pred __pred, _Proj __proj = {}) - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + while (__remainder <= __tail_size) + { + __first += __remainder; + __tail_size -= __remainder; + auto __backtrack = __first; + while (__value_comp(std::__invoke(__proj, *--__backtrack))) + { + if (--__remainder == 0) + return {__first - __count, __first}; + } + } + auto __i = __first + __tail_size; + return {__i, __i}; + } + else { - *__result = *__first; - ++__result; + __first = ranges::find_if(__first, __last, __value_comp, __proj); + while (__first != __last) + { + auto __n = __count; + auto __i = __first; + ++__i; + while (__i != __last && __n != 1 + && __value_comp(std::__invoke(__proj, *__i))) + { + ++__i; + --__n; + } + if (__n == 1) + return {__first, __i}; + if (__i == __last) + return {__i, __i}; + __first = ranges::find_if(++__i, __last, __value_comp, __proj); + } + return {__first, __first}; } - return {std::move(__first), std::move(__result)}; - } - - template, _Proj>> _Pred> - requires indirectly_copyable, _Out> - constexpr copy_if_result, _Out> - copy_if(_Range&& __r, _Out __result, _Pred __pred, _Proj __proj = {}) - { - return ranges::copy_if(ranges::begin(__r), ranges::end(__r), - std::move(__result), - std::move(__pred), std::move(__proj)); - } - - template - using swap_ranges_result = mismatch_result<_Iter1, _Iter2>; + } - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2> - requires indirectly_swappable<_Iter1, _Iter2> - constexpr swap_ranges_result<_Iter1, _Iter2> - swap_ranges(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2) - { - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - ranges::iter_swap(__first1, __first2); - return {std::move(__first1), std::move(__first2)}; - } - - template - requires indirectly_swappable, iterator_t<_Range2>> - constexpr swap_ranges_result, - safe_iterator_t<_Range2>> - swap_ranges(_Range1&& __r1, _Range2&& __r2) - { - return ranges::swap_ranges(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2)); - } + template + requires indirectly_comparable, const _Tp*, _Pred, _Proj> + constexpr safe_subrange_t<_Range> + operator()(_Range&& __r, range_difference_t<_Range> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__count), __value, + std::move(__pred), std::move(__proj)); + } + }; - template - using unary_transform_result = copy_result<_Iter, _Out>; + inline constexpr __search_n_fn search_n{}; - template _Sent, - weakly_incrementable _Out, - copy_constructible _Fp, typename _Proj = identity> - requires indirectly_writable<_Out, - indirect_result_t<_Fp&, - projected<_Iter, _Proj>>> - constexpr unary_transform_result<_Iter, _Out> - transform(_Iter __first1, _Sent __last1, _Out __result, - _Fp __op, _Proj __proj = {}) - { - for (; __first1 != __last1; ++__first1, (void)++__result) - *__result = std::__invoke(__op, std::__invoke(__proj, *__first1)); - return {std::move(__first1), std::move(__result)}; - } - - template - requires indirectly_writable<_Out, - indirect_result_t<_Fp&, - projected, _Proj>>> - constexpr unary_transform_result, _Out> - transform(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) - { - return ranges::transform(ranges::begin(__r), ranges::end(__r), - std::move(__result), - std::move(__op), std::move(__proj)); - } + struct __find_end_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if constexpr (bidirectional_iterator<_Iter1> + && bidirectional_iterator<_Iter2>) + { + auto __i1 = ranges::next(__first1, __last1); + auto __i2 = ranges::next(__first2, __last2); + auto __rresult + = ranges::search(reverse_iterator<_Iter1>{__i1}, + reverse_iterator<_Iter1>{__first1}, + reverse_iterator<_Iter2>{__i2}, + reverse_iterator<_Iter2>{__first2}, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + auto __result_first = ranges::end(__rresult).base(); + auto __result_last = ranges::begin(__rresult).base(); + if (__result_last == __first1) + return {__i1, __i1}; + else + return {__result_first, __result_last}; + } + else + { + auto __i = ranges::next(__first1, __last1); + if (__first2 == __last2) + return {__i, __i}; + + auto __result_begin = __i; + auto __result_end = __i; + for (;;) + { + auto __new_range = ranges::search(__first1, __last1, + __first2, __last2, + __pred, __proj1, __proj2); + auto __new_result_begin = ranges::begin(__new_range); + auto __new_result_end = ranges::end(__new_range); + if (__new_result_begin == __last1) + return {__result_begin, __result_end}; + else + { + __result_begin = __new_result_begin; + __result_end = __new_result_end; + __first1 = __result_begin; + ++__first1; + } + } + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr safe_subrange_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __find_end_fn find_end{}; + + struct __adjacent_find_fn + { + template _Sent, + typename _Proj = identity, + indirect_binary_predicate, + projected<_Iter, _Proj>> _Pred + = ranges::equal_to> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + auto __next = __first; + for (; ++__next != __last; __first = __next) + { + if (std::__invoke(__pred, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + return __first; + } + return __next; + } + + template, _Proj>, + projected, _Proj>> _Pred = ranges::equal_to> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __adjacent_find_fn adjacent_find{}; + + struct __is_permutation_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_equivalence_relation, + projected<_Iter2, _Proj2>> _Pred + = ranges::equal_to> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + + if constexpr (__sized_iters) + { + if (__first1 == __last1) + return true; + } + else + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 == 0 && __d2 == 0) + return true; + if (__d1 != __d2) + return false; + } + + for (auto __scan = __first1; __scan != __last1; ++__scan) + { + auto __proj_scan = std::__invoke(__proj1, *__scan); + auto __comp_scan = [&] (_Tp&& __arg) { + return std::__invoke(__pred, __proj_scan, + std::forward<_Tp>(__arg)); + }; + if (__scan != ranges::find_if(__first1, __scan, + __comp_scan, __proj1)) + continue; // We've seen this one before. + + auto __matches = ranges::count_if(__first2, __last2, + __comp_scan, __proj2); + if (__matches == 0 + || ranges::count_if(__scan, __last1, + __comp_scan, __proj1) != __matches) + return false; + } + return true; + } + + template, _Proj1>, + projected, _Proj2>> _Pred = ranges::equal_to> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __is_permutation_fn is_permutation{}; + + template + using copy_if_result = copy_result<_Iter, _Out>; + + struct __copy_if_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template, _Proj>> _Pred> + requires indirectly_copyable, _Out> + constexpr copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __copy_if_fn copy_if{}; + + template + using swap_ranges_result = mismatch_result<_Iter1, _Iter2>; + + struct __swap_ranges_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2> + requires indirectly_swappable<_Iter1, _Iter2> + constexpr swap_ranges_result<_Iter1, _Iter2> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2) const + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + ranges::iter_swap(__first1, __first2); + return {std::move(__first1), std::move(__first2)}; + } + + template + requires indirectly_swappable, iterator_t<_Range2>> + constexpr swap_ranges_result, + safe_iterator_t<_Range2>> + operator()(_Range1&& __r1, _Range2&& __r2) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2)); + } + }; + + inline constexpr __swap_ranges_fn swap_ranges{}; + + template + using unary_transform_result = copy_result<_Iter, _Out>; template struct binary_transform_result @@ -813,1373 +873,1590 @@ namespace ranges { return {std::move(in1), std::move(in2), std::move(out)}; } }; - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, copy_constructible _Fp, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_writable<_Out, - indirect_result_t<_Fp&, - projected<_Iter1, _Proj1>, - projected<_Iter2, _Proj2>>> - constexpr binary_transform_result<_Iter1, _Iter2, _Out> - transform(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Out __result, _Fp __binary_op, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2, ++__result) - *__result = std::__invoke(__binary_op, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2)); - return {std::move(__first1), std::move(__first2), std::move(__result)}; - } - - template - requires indirectly_writable<_Out, - indirect_result_t<_Fp&, - projected, _Proj1>, - projected, _Proj2>>> - constexpr binary_transform_result, - safe_iterator_t<_Range2>, _Out> - transform(_Range1&& __r1, _Range2&& __r2, _Out __result, - _Fp __binary_op, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::transform(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__binary_op), - std::move(__proj1), std::move(__proj2)); - } - - template _Sent, - typename _Tp1, typename _Tp2, typename _Proj = identity> - requires indirectly_writable<_Iter, const _Tp2&> - && indirect_binary_predicate, - const _Tp1*> - constexpr _Iter - replace(_Iter __first, _Sent __last, - const _Tp1& __old_value, const _Tp2& __new_value, - _Proj __proj = {}) - { - for (; __first != __last; ++__first) - if (std::__invoke(__proj, *__first) == __old_value) - *__first = __new_value; - return __first; - } - - template - requires indirectly_writable, const _Tp2&> - && indirect_binary_predicate, _Proj>, - const _Tp1*> - constexpr safe_iterator_t<_Range> - replace(_Range&& __r, - const _Tp1& __old_value, const _Tp2& __new_value, - _Proj __proj = {}) - { - return ranges::replace(ranges::begin(__r), ranges::end(__r), - __old_value, __new_value, std::move(__proj)); - } - - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_writable<_Iter, const _Tp&> - constexpr _Iter - replace_if(_Iter __first, _Sent __last, - _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - *__first = __new_value; - return std::move(__first); - } - - template, _Proj>> _Pred> - requires indirectly_writable, const _Tp&> - constexpr safe_iterator_t<_Range> - replace_if(_Range&& __r, - _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) - { - return ranges::replace_if(ranges::begin(__r), ranges::end(__r), - std::move(__pred), __new_value, - std::move(__proj)); - } + struct __transform_fn + { + template _Sent, + weakly_incrementable _Out, + copy_constructible _Fp, typename _Proj = identity> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected<_Iter, _Proj>>> + constexpr unary_transform_result<_Iter, _Out> + operator()(_Iter __first1, _Sent __last1, _Out __result, + _Fp __op, _Proj __proj = {}) const + { + for (; __first1 != __last1; ++__first1, (void)++__result) + *__result = std::__invoke(__op, std::__invoke(__proj, *__first1)); + return {std::move(__first1), std::move(__result)}; + } - template - using replace_copy_result = copy_result<_Iter, _Out>; + template + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj>>> + constexpr unary_transform_result, _Out> + operator()(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__op), std::move(__proj)); + } - template _Sent, - typename _Tp1, typename _Tp2, output_iterator _Out, - typename _Proj = identity> - requires indirectly_copyable<_Iter, _Out> - && indirect_binary_predicate, const _Tp1*> - constexpr replace_copy_result<_Iter, _Out> - replace_copy(_Iter __first, _Sent __last, _Out __result, - const _Tp1& __old_value, const _Tp2& __new_value, - _Proj __proj = {}) - { - for (; __first != __last; ++__first, (void)++__result) - if (std::__invoke(__proj, *__first) == __old_value) - *__result = __new_value; - else - *__result = *__first; - return {std::move(__first), std::move(__result)}; - } - - template _Out, typename _Proj = identity> - requires indirectly_copyable, _Out> - && indirect_binary_predicate, _Proj>, - const _Tp1*> - constexpr replace_copy_result, _Out> - replace_copy(_Range&& __r, _Out __result, - const _Tp1& __old_value, const _Tp2& __new_value, - _Proj __proj = {}) - { - return ranges::replace_copy(ranges::begin(__r), ranges::end(__r), - std::move(__result), __old_value, - __new_value, std::move(__proj)); - } + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, copy_constructible _Fp, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>>> + constexpr binary_transform_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Out __result, _Fp __binary_op, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2, ++__result) + *__result = std::__invoke(__binary_op, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2)); + return {std::move(__first1), std::move(__first2), std::move(__result)}; + } - template - using replace_copy_if_result = copy_result<_Iter, _Out>; + template + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj1>, + projected, _Proj2>>> + constexpr binary_transform_result, + safe_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Fp __binary_op, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__binary_op), + std::move(__proj1), std::move(__proj2)); + } + }; - template _Sent, - typename _Tp, output_iterator _Out, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_Iter, _Out> - constexpr replace_copy_if_result<_Iter, _Out> - replace_copy_if(_Iter __first, _Sent __last, _Out __result, - _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) - { - for (; __first != __last; ++__first, (void)++__result) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - *__result = __new_value; - else - *__result = *__first; - return {std::move(__first), std::move(__result)}; - } - - template _Out, - typename _Proj = identity, - indirect_unary_predicate, _Proj>> _Pred> - requires indirectly_copyable, _Out> - constexpr replace_copy_if_result, _Out> - replace_copy_if(_Range&& __r, _Out __result, - _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) - { - return ranges::replace_copy_if(ranges::begin(__r), ranges::end(__r), - std::move(__result), std::move(__pred), - __new_value, std::move(__proj)); - } - - template - requires invocable<_Fp&> - && indirectly_writable<_Out, invoke_result_t<_Fp&>> - constexpr _Out - generate_n(_Out __first, iter_difference_t<_Out> __n, _Fp __gen) - { - for (; __n > 0; --__n, (void)++__first) - *__first = std::__invoke(__gen); - return __first; - } - - template _Sent, - copy_constructible _Fp> - requires invocable<_Fp&> - && indirectly_writable<_Out, invoke_result_t<_Fp&>> - constexpr _Out - generate(_Out __first, _Sent __last, _Fp __gen) - { - for (; __first != __last; ++__first) - *__first = std::__invoke(__gen); - return __first; - } - - template - requires invocable<_Fp&> && output_range<_Range, invoke_result_t<_Fp&>> - constexpr safe_iterator_t<_Range> - generate(_Range&& __r, _Fp __gen) - { - return ranges::generate(ranges::begin(__r), ranges::end(__r), - std::move(__gen)); - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr subrange<_Iter> - remove_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - __first = ranges::find_if(__first, __last, __pred, __proj); - if (__first == __last) - return {__first, __first}; + inline constexpr __transform_fn transform{}; - auto __result = __first; - ++__first; - for (; __first != __last; ++__first) - if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - { - *__result = std::move(*__first); - ++__result; - } + struct __replace_fn + { + template _Sent, + typename _Tp1, typename _Tp2, typename _Proj = identity> + requires indirectly_writable<_Iter, const _Tp2&> + && indirect_binary_predicate, + const _Tp1*> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __old_value) + *__first = __new_value; + return __first; + } - return {__result, __first}; - } + template + requires indirectly_writable, const _Tp2&> + && indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __old_value, __new_value, std::move(__proj)); + } + }; - template, _Proj>> _Pred> - requires permutable> - constexpr safe_subrange_t<_Range> - remove_if(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::remove_if(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - - template _Sent, - typename _Tp, typename _Proj = identity> - requires indirect_binary_predicate, - const _Tp*> - constexpr subrange<_Iter> - remove(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) - { - auto __pred = [&] (auto&& __arg) { - return std::forward(__arg) == __value; - }; - return ranges::remove_if(__first, __last, - std::move(__pred), std::move(__proj)); - } - - template - requires permutable> - && indirect_binary_predicate, _Proj>, - const _Tp*> - constexpr safe_subrange_t<_Range> - remove(_Range&& __r, const _Tp& __value, _Proj __proj = {}) - { - return ranges::remove(ranges::begin(__r), ranges::end(__r), - __value, std::move(__proj)); - } + inline constexpr __replace_fn replace{}; - template - using remove_copy_if_result = copy_result<_Iter, _Out>; + struct __replace_if_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_writable<_Iter, const _Tp&> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__first = __new_value; + return std::move(__first); + } - template _Sent, - weakly_incrementable _Out, typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_Iter, _Out> - constexpr remove_copy_if_result<_Iter, _Out> - remove_copy_if(_Iter __first, _Sent __last, _Out __result, - _Pred __pred, _Proj __proj = {}) - { - for (; __first != __last; ++__first) - if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - { - *__result = *__first; - ++__result; - } - return {std::move(__first), std::move(__result)}; - } - - template, _Proj>> _Pred> - requires indirectly_copyable, _Out> - constexpr remove_copy_if_result, _Out> - remove_copy_if(_Range&& __r, _Out __result, - _Pred __pred, _Proj __proj = {}) - { - return ranges::remove_copy_if(ranges::begin(__r), ranges::end(__r), - std::move(__result), - std::move(__pred), std::move(__proj)); - } + template, _Proj>> _Pred> + requires indirectly_writable, const _Tp&> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), __new_value, + std::move(__proj)); + } + }; + + inline constexpr __replace_if_fn replace_if{}; template - using remove_copy_result = copy_result<_Iter, _Out>; + using replace_copy_result = copy_result<_Iter, _Out>; - template _Sent, - weakly_incrementable _Out, typename _Tp, typename _Proj = identity> - requires indirectly_copyable<_Iter, _Out> - && indirect_binary_predicate, - const _Tp*> - constexpr remove_copy_result<_Iter, _Out> - remove_copy(_Iter __first, _Sent __last, _Out __result, - const _Tp& __value, _Proj __proj = {}) - { - for (; __first != __last; ++__first) - if (!(std::__invoke(__proj, *__first) == __value)) - { + struct __replace_copy_fn + { + template _Sent, + typename _Tp1, typename _Tp2, output_iterator _Out, + typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, const _Tp1*> + constexpr replace_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__proj, *__first) == __old_value) + *__result = __new_value; + else *__result = *__first; - ++__result; - } - return {std::move(__first), std::move(__result)}; - } - - template - requires indirectly_copyable, _Out> - && indirect_binary_predicate, _Proj>, - const _Tp*> - constexpr remove_copy_result, _Out> - remove_copy(_Range&& __r, _Out __result, - const _Tp& __value, _Proj __proj = {}) - { - return ranges::remove_copy(ranges::begin(__r), ranges::end(__r), - std::move(__result), __value, - std::move(__proj)); - - } - - template _Sent, - typename _Proj = identity, - indirect_equivalence_relation< - projected<_Iter, _Proj>> _Comp = ranges::equal_to> - constexpr subrange<_Iter> - unique(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) - { - __first = ranges::adjacent_find(__first, __last, __comp, __proj); - if (__first == __last) - return {__first, __first}; + return {std::move(__first), std::move(__result)}; + } - auto __dest = __first; - ++__first; - while (++__first != __last) - if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__dest), - std::__invoke(__proj, *__first))) - *++__dest = std::move(*__first); - return {++__dest, __first}; - } - - template, _Proj>> _Comp = ranges::equal_to> - requires permutable> - constexpr safe_subrange_t<_Range> - unique(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::unique(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + template _Out, typename _Proj = identity> + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr replace_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), __old_value, + __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_copy_fn replace_copy{}; template - using unique_copy_result = copy_result<_Iter, _Out>; + using replace_copy_if_result = copy_result<_Iter, _Out>; - template _Sent, - weakly_incrementable _Out, typename _Proj = identity, - indirect_equivalence_relation< - projected<_Iter, _Proj>> _Comp = ranges::equal_to> - requires indirectly_copyable<_Iter, _Out> - && (forward_iterator<_Iter> - || (input_iterator<_Out> - && same_as, iter_value_t<_Out>>) - || indirectly_copyable_storable<_Iter, _Out>) - constexpr unique_copy_result<_Iter, _Out> - unique_copy(_Iter __first, _Sent __last, _Out __result, - _Comp __comp = {}, _Proj __proj = {}) - { - if (__first == __last) + struct __replace_copy_if_fn + { + template _Sent, + typename _Tp, output_iterator _Out, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr replace_copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__result = __new_value; + else + *__result = *__first; return {std::move(__first), std::move(__result)}; + } - // TODO: perform a closer comparison with reference implementations - if constexpr (forward_iterator<_Iter>) - { - auto __next = __first; - *__result = *__next; - while (++__next != __last) - if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__first), - std::__invoke(__proj, *__next))) - { - __first = __next; - *++__result = *__first; - } - return {__next, std::move(++__result)}; - } - else if constexpr (input_iterator<_Out> - && same_as, iter_value_t<_Out>>) - { - *__result = *__first; - while (++__first != __last) - if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__result), - std::__invoke(__proj, *__first))) - *++__result = *__first; - return {std::move(__first), std::move(++__result)}; - } - else // indirectly_copyable_storable<_Iter, _Out> - { - auto __value = *__first; - *__result = __value; - while (++__first != __last) - { - if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__first), - std::__invoke(__proj, __value))) - { - __value = *__first; - *++__result = __value; - } - } - return {std::move(__first), std::move(++__result)}; - } - } - - template, _Proj>> _Comp = ranges::equal_to> - requires indirectly_copyable, _Out> - && (forward_iterator> - || (input_iterator<_Out> - && same_as, iter_value_t<_Out>>) - || indirectly_copyable_storable, _Out>) - constexpr unique_copy_result, _Out> - unique_copy(_Range&& __r, _Out __result, - _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::unique_copy(ranges::begin(__r), ranges::end(__r), - std::move(__result), - std::move(__comp), std::move(__proj)); - } - - template _Sent> - requires permutable<_Iter> - constexpr _Iter - reverse(_Iter __first, _Sent __last) - { - auto __i = ranges::next(__first, __last); - auto __tail = __i; + template _Out, + typename _Proj = identity, + indirect_unary_predicate, _Proj>> _Pred> + requires indirectly_copyable, _Out> + constexpr replace_copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), std::move(__pred), + __new_value, std::move(__proj)); + } + }; - if constexpr (random_access_iterator<_Iter>) - { - if (__first != __last) - { - --__tail; - while (__first < __tail) - { - ranges::iter_swap(__first, __tail); - ++__first; - --__tail; - } - } - return __i; - } - else - { - for (;;) - if (__first == __tail || __first == --__tail) - break; - else - { - ranges::iter_swap(__first, __tail); - ++__first; - } - return __i; - } - } + inline constexpr __replace_copy_if_fn replace_copy_if{}; - template - requires permutable> - constexpr safe_iterator_t<_Range> - reverse(_Range&& __r) - { - return ranges::reverse(ranges::begin(__r), ranges::end(__r)); - } + struct __generate_n_fn + { + template + requires invocable<_Fp&> + && indirectly_writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + operator()(_Out __first, iter_difference_t<_Out> __n, _Fp __gen) const + { + for (; __n > 0; --__n, (void)++__first) + *__first = std::__invoke(__gen); + return __first; + } + }; - template - using reverse_copy_result = copy_result<_Iter, _Out>; + inline constexpr __generate_n_fn generate_n{}; - template _Sent, - weakly_incrementable _Out> - requires indirectly_copyable<_Iter, _Out> - constexpr reverse_copy_result<_Iter, _Out> - reverse_copy(_Iter __first, _Sent __last, _Out __result) - { - auto __i = ranges::next(__first, __last); - auto __tail = __i; - while (__first != __tail) - { - --__tail; - *__result = *__tail; - ++__result; - } - return {__i, __result}; - } + struct __generate_fn + { + template _Sent, + copy_constructible _Fp> + requires invocable<_Fp&> + && indirectly_writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + operator()(_Out __first, _Sent __last, _Fp __gen) const + { + for (; __first != __last; ++__first) + *__first = std::__invoke(__gen); + return __first; + } - template - requires indirectly_copyable, _Out> - constexpr reverse_copy_result, _Out> - reverse_copy(_Range&& __r, _Out __result) - { - return ranges::reverse_copy(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } + template + requires invocable<_Fp&> && output_range<_Range, invoke_result_t<_Fp&>> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Fp __gen) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__gen)); + } + }; - template _Sent> - constexpr subrange<_Iter> - rotate(_Iter __first, _Iter __middle, _Sent __last) - { - auto __lasti = ranges::next(__first, __last); - if (__first == __middle) - return {__lasti, __lasti}; - if (__last == __middle) - return {std::move(__first), std::move(__lasti)}; + inline constexpr __generate_fn generate{}; - if constexpr (random_access_iterator<_Iter>) - { - auto __n = __lasti - __first; - auto __k = __middle - __first; + struct __remove_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + __first = ranges::find_if(__first, __last, __pred, __proj); + if (__first == __last) + return {__first, __first}; - if (__k == __n - __k) + auto __result = __first; + ++__first; + for (; __first != __last; ++__first) + if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) { - ranges::swap_ranges(__first, __middle, __middle, __middle + __k); - return {std::move(__middle), std::move(__lasti)}; + *__result = std::move(*__first); + ++__result; } - auto __p = __first; - auto __ret = __first + (__lasti - __middle); - - for (;;) - { - if (__k < __n - __k) - { - // TODO: is_pod is deprecated, but this condition is - // consistent with the STL implementation. - if constexpr (__is_pod(iter_value_t<_Iter>)) - if (__k == 1) - { - auto __t = std::move(*__p); - ranges::move(__p + 1, __p + __n, __p); - *(__p + __n - 1) = std::move(__t); - return {std::move(__ret), std::move(__lasti)}; - } - auto __q = __p + __k; - for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) - { - ranges::iter_swap(__p, __q); - ++__p; - ++__q; - } - __n %= __k; - if (__n == 0) - return {std::move(__ret), std::move(__lasti)}; - ranges::swap(__n, __k); - __k = __n - __k; - } - else - { - __k = __n - __k; - // TODO: is_pod is deprecated, but this condition is - // consistent with the STL implementation. - if constexpr (__is_pod(iter_value_t<_Iter>)) - if (__k == 1) - { - auto __t = std::move(*(__p + __n - 1)); - ranges::move_backward(__p, __p + __n - 1, __p + __n); - *__p = std::move(__t); - return {std::move(__ret), std::move(__lasti)}; - } - auto __q = __p + __n; - __p = __q - __k; - for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) - { - --__p; - --__q; - ranges::iter_swap(__p, __q); - } - __n %= __k; - if (__n == 0) - return {std::move(__ret), std::move(__lasti)}; - std::swap(__n, __k); - } - } - } - else if constexpr (bidirectional_iterator<_Iter>) - { - auto __tail = __lasti; + return {__result, __first}; + } - ranges::reverse(__first, __middle); - ranges::reverse(__middle, __tail); + template, _Proj>> _Pred> + requires permutable> + constexpr safe_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; - while (__first != __middle && __middle != __tail) - { - ranges::iter_swap(__first, --__tail); - ++__first; - } + inline constexpr __remove_if_fn remove_if{}; - if (__first == __middle) - { - ranges::reverse(__middle, __tail); - return {std::move(__tail), std::move(__lasti)}; - } - else + struct __remove_fn + { + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const + { + auto __pred = [&] (auto&& __arg) { + return std::forward(__arg) == __value; + }; + return ranges::remove_if(__first, __last, + std::move(__pred), std::move(__proj)); + } + + template + requires permutable> + && indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr safe_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __remove_fn remove{}; + + template + using remove_copy_if_result = copy_result<_Iter, _Out>; + + struct __remove_copy_if_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr remove_copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) { - ranges::reverse(__first, __middle); - return {std::move(__first), std::move(__lasti)}; + *__result = *__first; + ++__result; } - } - else - { - auto __first2 = __middle; - do - { - ranges::iter_swap(__first, __first2); - ++__first; - ++__first2; - if (__first == __middle) - __middle = __first2; - } while (__first2 != __last); + return {std::move(__first), std::move(__result)}; + } - auto __ret = __first; + template, _Proj>> _Pred> + requires indirectly_copyable, _Out> + constexpr remove_copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + }; - __first2 = __middle; + inline constexpr __remove_copy_if_fn remove_copy_if{}; - while (__first2 != __last) + template + using remove_copy_result = copy_result<_Iter, _Out>; + + struct __remove_copy_fn + { + template _Sent, + weakly_incrementable _Out, typename _Tp, typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, + const _Tp*> + constexpr remove_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + const _Tp& __value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!(std::__invoke(__proj, *__first) == __value)) { - ranges::iter_swap(__first, __first2); - ++__first; - ++__first2; - if (__first == __middle) - __middle = __first2; - else if (__first2 == __last) - __first2 = __middle; + *__result = *__first; + ++__result; } - return {std::move(__ret), std::move(__lasti)}; - } - } + return {std::move(__first), std::move(__result)}; + } - template - requires permutable> - constexpr safe_subrange_t<_Range> - rotate(_Range&& __r, iterator_t<_Range> __middle) - { - return ranges::rotate(ranges::begin(__r), - std::move(__middle), - ranges::end(__r)); - } + template + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr remove_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), __value, + std::move(__proj)); + } + }; - template - using rotate_copy_result = copy_result<_Iter, _Out>; + inline constexpr __remove_copy_fn remove_copy{}; - template _Sent, - weakly_incrementable _Out> - requires indirectly_copyable<_Iter, _Out> - constexpr rotate_copy_result<_Iter, _Out> - rotate_copy(_Iter __first, _Iter __middle, _Sent __last, _Out __result) - { - auto __copy1 = ranges::copy(__middle, - std::move(__last), - std::move(__result)); - auto __copy2 = ranges::copy(std::move(__first), - std::move(__middle), - std::move(__copy1.out)); - return { std::move(__copy1.in), std::move(__copy2.out) }; - } - - template - requires indirectly_copyable, _Out> - constexpr rotate_copy_result, _Out> - rotate_copy(_Range&& __r, iterator_t<_Range> __middle, _Out __result) - { - return ranges::rotate_copy(ranges::begin(__r), - std::move(__middle), - ranges::end(__r), - std::move(__result)); - } + struct __unique_fn + { + template _Sent, + typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const + { + __first = ranges::adjacent_find(__first, __last, __comp, __proj); + if (__first == __last) + return {__first, __first}; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - template _Sent, - typename _Gen> - requires permutable<_Iter> - && uniform_random_bit_generator> - _Iter - shuffle(_Iter __first, _Sent __last, _Gen&& __g) - { - auto __lasti = ranges::next(__first, __last); - std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g)); - return __lasti; - } - - template - requires permutable> - && uniform_random_bit_generator> - safe_iterator_t<_Range> - shuffle(_Range&& __r, _Gen&& __g) - { - return ranges::shuffle(ranges::begin(__r), ranges::end(__r), - std::forward<_Gen>(__g)); - } -#endif + auto __dest = __first; + ++__first; + while (++__first != __last) + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__dest), + std::__invoke(__proj, *__first))) + *++__dest = std::move(*__first); + return {++__dest, __first}; + } - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - push_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) - { - auto __lasti = ranges::next(__first, __last); - std::push_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr safe_iterator_t<_Range> - push_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::push_heap(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + template, _Proj>> _Comp = ranges::equal_to> + requires permutable> + constexpr safe_subrange_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - pop_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) - { - auto __lasti = ranges::next(__first, __last); - std::pop_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr safe_iterator_t<_Range> - pop_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::pop_heap(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + inline constexpr __unique_fn unique{}; - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - make_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) - { - auto __lasti = ranges::next(__first, __last); - std::make_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr safe_iterator_t<_Range> - make_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::make_heap(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + template + using unique_copy_result = copy_result<_Iter, _Out>; - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - sort_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) - { - auto __lasti = ranges::next(__first, __last); - std::sort_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr safe_iterator_t<_Range> - sort_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::sort_heap(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - is_heap_until(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - iter_difference_t<_Iter> __n = ranges::distance(__first, __last); - iter_difference_t<_Iter> __parent = 0, __child = 1; - for (; __child < __n; ++__child) - if (std::__invoke(__comp, - std::__invoke(__proj, *(__first + __parent)), - std::__invoke(__proj, *(__first + __child)))) - return __first + __child; - else if ((__child & 1) == 0) - ++__parent; - - return __first + __n; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr safe_iterator_t<_Range> - is_heap_until(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::is_heap_until(ranges::begin(__r), ranges::end(__r), + struct __unique_copy_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable<_Iter, _Out> + && (forward_iterator<_Iter> + || (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + || indirectly_copyable_storable<_Iter, _Out>) + constexpr unique_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), std::move(__result)}; + + // TODO: perform a closer comparison with reference implementations + if constexpr (forward_iterator<_Iter>) + { + auto __next = __first; + *__result = *__next; + while (++__next != __last) + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + { + __first = __next; + *++__result = *__first; + } + return {__next, std::move(++__result)}; + } + else if constexpr (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + { + *__result = *__first; + while (++__first != __last) + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__result), + std::__invoke(__proj, *__first))) + *++__result = *__first; + return {std::move(__first), std::move(++__result)}; + } + else // indirectly_copyable_storable<_Iter, _Out> + { + auto __value = *__first; + *__result = __value; + while (++__first != __last) + { + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, __value))) + { + __value = *__first; + *++__result = __value; + } + } + return {std::move(__first), std::move(++__result)}; + } + } + + template, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable, _Out> + && (forward_iterator> + || (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + || indirectly_copyable_storable, _Out>) + constexpr unique_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr bool - is_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) - { - return (__last - == ranges::is_heap_until(__first, __last, - std::move(__comp), - std::move(__proj))); - } - - template, _Proj>> - _Comp = ranges::less> - constexpr bool - is_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::is_heap(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - sort(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) - { - auto __lasti = ranges::next(__first, __last); - std::sort(std::move(__first), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr safe_iterator_t<_Range> - sort(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::sort(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - _Iter - stable_sort(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - auto __lasti = ranges::next(__first, __last); - std::stable_sort(std::move(__first), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - safe_iterator_t<_Range> - stable_sort(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::stable_sort(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - partial_sort(_Iter __first, _Iter __middle, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - if (__first == __middle) - return ranges::next(__first, __last); - - ranges::make_heap(__first, __middle, __comp, __proj); - auto __i = __middle; - for (; __i != __last; ++__i) - if (std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__first))) + } + }; + + inline constexpr __unique_copy_fn unique_copy{}; + + struct __reverse_fn + { + template _Sent> + requires permutable<_Iter> + constexpr _Iter + operator()(_Iter __first, _Sent __last) const + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + + if constexpr (random_access_iterator<_Iter>) { - ranges::pop_heap(__first, __middle, __comp, __proj); - ranges::iter_swap(__middle-1, __i); - ranges::push_heap(__first, __middle, __comp, __proj); + if (__first != __last) + { + --__tail; + while (__first < __tail) + { + ranges::iter_swap(__first, __tail); + ++__first; + --__tail; + } + } + return __i; } - ranges::sort_heap(__first, __middle, __comp, __proj); + else + { + for (;;) + if (__first == __tail || __first == --__tail) + break; + else + { + ranges::iter_swap(__first, __tail); + ++__first; + } + return __i; + } + } - return __i; - } + template + requires permutable> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; - template - requires sortable, _Comp, _Proj> - constexpr safe_iterator_t<_Range> - partial_sort(_Range&& __r, iterator_t<_Range> __middle, - _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::partial_sort(ranges::begin(__r), - std::move(__middle), - ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + inline constexpr __reverse_fn reverse{}; template - using partial_sort_copy_result = copy_result<_Iter, _Out>; + using reverse_copy_result = copy_result<_Iter, _Out>; - template _Sent1, - random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_copyable<_Iter1, _Iter2> - && sortable<_Iter2, _Comp, _Proj2> - && indirect_strict_weak_order<_Comp, - projected<_Iter1, _Proj1>, - projected<_Iter2, _Proj2>> - constexpr partial_sort_copy_result<_Iter1, _Iter2> - partial_sort_copy(_Iter1 __first, _Sent1 __last, - _Iter2 __result_first, _Sent2 __result_last, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - if (__result_first == __result_last) - { - // TODO: Eliminating the variable __lasti triggers an ICE. - auto __lasti = ranges::next(std::move(__first), - std::move(__last)); - return {std::move(__lasti), std::move(__result_first)}; - } + struct __reverse_copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr reverse_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + while (__first != __tail) + { + --__tail; + *__result = *__tail; + ++__result; + } + return {__i, __result}; + } - auto __result_real_last = __result_first; - while (__first != __last && __result_real_last != __result_last) - { - *__result_real_last = *__first; - ++__result_real_last; - ++__first; - } + template + requires indirectly_copyable, _Out> + constexpr reverse_copy_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __reverse_copy_fn reverse_copy{}; + + struct __rotate_fn + { + template _Sent> + constexpr subrange<_Iter> + operator()(_Iter __first, _Iter __middle, _Sent __last) const + { + auto __lasti = ranges::next(__first, __last); + if (__first == __middle) + return {__lasti, __lasti}; + if (__last == __middle) + return {std::move(__first), std::move(__lasti)}; + + if constexpr (random_access_iterator<_Iter>) + { + auto __n = __lasti - __first; + auto __k = __middle - __first; + + if (__k == __n - __k) + { + ranges::swap_ranges(__first, __middle, __middle, __middle + __k); + return {std::move(__middle), std::move(__lasti)}; + } + + auto __p = __first; + auto __ret = __first + (__lasti - __middle); + + for (;;) + { + if (__k < __n - __k) + { + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*__p); + ranges::move(__p + 1, __p + __n, __p); + *(__p + __n - 1) = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + ranges::iter_swap(__p, __q); + ++__p; + ++__q; + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + ranges::swap(__n, __k); + __k = __n - __k; + } + else + { + __k = __n - __k; + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*(__p + __n - 1)); + ranges::move_backward(__p, __p + __n - 1, __p + __n); + *__p = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __n; + __p = __q - __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + --__p; + --__q; + ranges::iter_swap(__p, __q); + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + std::swap(__n, __k); + } + } + } + else if constexpr (bidirectional_iterator<_Iter>) + { + auto __tail = __lasti; - ranges::make_heap(__result_first, __result_real_last, __comp, __proj2); - for (; __first != __last; ++__first) - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first), - std::__invoke(__proj2, *__result_first))) + ranges::reverse(__first, __middle); + ranges::reverse(__middle, __tail); + + while (__first != __middle && __middle != __tail) + { + ranges::iter_swap(__first, --__tail); + ++__first; + } + + if (__first == __middle) + { + ranges::reverse(__middle, __tail); + return {std::move(__tail), std::move(__lasti)}; + } + else + { + ranges::reverse(__first, __middle); + return {std::move(__first), std::move(__lasti)}; + } + } + else { - ranges::pop_heap(__result_first, __result_real_last, - __comp, __proj2); - *(__result_real_last-1) = *__first; - ranges::push_heap(__result_first, __result_real_last, - __comp, __proj2); + auto __first2 = __middle; + do + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + } while (__first2 != __last); + + auto __ret = __first; + + __first2 = __middle; + + while (__first2 != __last) + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + else if (__first2 == __last) + __first2 = __middle; + } + return {std::move(__ret), std::move(__lasti)}; } - ranges::sort_heap(__result_first, __result_real_last, __comp, __proj2); - - return {std::move(__first), std::move(__result_real_last)}; - } - - template - requires indirectly_copyable, iterator_t<_Range2>> - && sortable, _Comp, _Proj2> - && indirect_strict_weak_order<_Comp, - projected, _Proj1>, - projected, _Proj2>> - constexpr partial_sort_copy_result, - safe_iterator_t<_Range2>> - partial_sort_copy(_Range1&& __r, _Range2&& __out, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::partial_sort_copy(ranges::begin(__r), ranges::end(__r), - ranges::begin(__out), ranges::end(__out), - std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - is_sorted_until(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - if (__first == __last) - return __first; + } - auto __next = __first; - for (++__next; __next != __last; __first = __next, (void)++__next) - if (std::__invoke(__comp, - std::__invoke(__proj, *__next), - std::__invoke(__proj, *__first))) - return __next; - return __next; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr safe_iterator_t<_Range> - is_sorted_until(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::is_sorted_until(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr bool - is_sorted(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) - { - if (__first == __last) - return true; + template + requires permutable> + constexpr safe_subrange_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle) const + { + return (*this)(ranges::begin(__r), + std::move(__middle), + ranges::end(__r)); + } + }; - auto __next = __first; - for (++__next; __next != __last; __first = __next, (void)++__next) - if (std::__invoke(__comp, - std::__invoke(__proj, *__next), - std::__invoke(__proj, *__first))) - return false; - return true; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr bool - is_sorted(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::is_sorted(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - nth_element(_Iter __first, _Iter __nth, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - auto __lasti = ranges::next(__first, __last); - std::nth_element(std::move(__first), std::move(__nth), __lasti, + inline constexpr __rotate_fn rotate{}; + + template + using rotate_copy_result = copy_result<_Iter, _Out>; + + struct __rotate_copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr rotate_copy_result<_Iter, _Out> + operator()(_Iter __first, _Iter __middle, _Sent __last, _Out __result) const + { + auto __copy1 = ranges::copy(__middle, + std::move(__last), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first), + std::move(__middle), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.out) }; + } + + template + requires indirectly_copyable, _Out> + constexpr rotate_copy_result, _Out> + operator()(_Range&& __r, iterator_t<_Range> __middle, _Out __result) const + { + return (*this)(ranges::begin(__r), + std::move(__middle), + ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __rotate_copy_fn rotate_copy{}; + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + struct __shuffle_fn + { + template _Sent, + typename _Gen> + requires permutable<_Iter> + && uniform_random_bit_generator> + _Iter + operator()(_Iter __first, _Sent __last, _Gen&& __g) const + { + auto __lasti = ranges::next(__first, __last); + std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g)); + return __lasti; + } + + template + requires permutable> + && uniform_random_bit_generator> + safe_iterator_t<_Range> + operator()(_Range&& __r, _Gen&& __g) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::forward<_Gen>(__g)); + } + }; + + inline constexpr __shuffle_fn shuffle{}; +#endif + + struct __push_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::push_heap(__first, __lasti, __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr safe_iterator_t<_Range> - nth_element(_Range&& __r, iterator_t<_Range> __nth, - _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::nth_element(ranges::begin(__r), std::move(__nth), - ranges::end(__r), + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - lower_bound(_Iter __first, _Sent __last, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) - { - auto __len = ranges::distance(__first, __last); + } + }; - while (__len > 0) - { - auto __half = __len / 2; - auto __middle = __first; - ranges::advance(__middle, __half); - if (std::__invoke(__comp, std::__invoke(__proj, *__middle), __value)) - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - else - __len = __half; - } - return __first; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr safe_iterator_t<_Range> - lower_bound(_Range&& __r, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::lower_bound(ranges::begin(__r), ranges::end(__r), - __value, + inline constexpr __push_heap_fn push_heap{}; + + struct __pop_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::pop_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - upper_bound(_Iter __first, _Sent __last, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) - { - auto __len = ranges::distance(__first, __last); + } + }; - while (__len > 0) - { - auto __half = __len / 2; - auto __middle = __first; - ranges::advance(__middle, __half); - if (std::__invoke(__comp, __value, std::__invoke(__proj, *__middle))) - __len = __half; - else - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - } - return __first; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr safe_iterator_t<_Range> - upper_bound(_Range&& __r, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::upper_bound(ranges::begin(__r), ranges::end(__r), - __value, + inline constexpr __pop_heap_fn pop_heap{}; + + struct __make_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::make_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr subrange<_Iter> - equal_range(_Iter __first, _Sent __last, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) - { - auto __len = ranges::distance(__first, __last); + } + }; - while (__len > 0) - { - auto __half = __len / 2; - auto __middle = __first; - ranges::advance(__middle, __half); + inline constexpr __make_heap_fn make_heap{}; + + struct __sort_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::sort_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __sort_heap_fn sort_heap{}; + + struct __is_heap_until_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = ranges::distance(__first, __last); + iter_difference_t<_Iter> __parent = 0, __child = 1; + for (; __child < __n; ++__child) + if (std::__invoke(__comp, + std::__invoke(__proj, *(__first + __parent)), + std::__invoke(__proj, *(__first + __child)))) + return __first + __child; + else if ((__child & 1) == 0) + ++__parent; + + return __first + __n; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_heap_until_fn is_heap_until{}; + + struct __is_heap_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const + { + return (__last + == ranges::is_heap_until(__first, __last, + std::move(__comp), + std::move(__proj))); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_heap_fn is_heap{}; + + struct __sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __sort_fn sort{}; + + struct __stable_sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::stable_sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __stable_sort_fn stable_sort{}; + + struct __partial_sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __middle) + return ranges::next(__first, __last); + + ranges::make_heap(__first, __middle, __comp, __proj); + auto __i = __middle; + for (; __i != __last; ++__i) if (std::__invoke(__comp, - std::__invoke(__proj, *__middle), - __value)) + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) { - __first = __middle; - ++__first; - __len = __len - __half - 1; + ranges::pop_heap(__first, __middle, __comp, __proj); + ranges::iter_swap(__middle-1, __i); + ranges::push_heap(__first, __middle, __comp, __proj); } - else if (std::__invoke(__comp, - __value, - std::__invoke(__proj, *__middle))) - __len = __half; - else + ranges::sort_heap(__first, __middle, __comp, __proj); + + return __i; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), + std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __partial_sort_fn partial_sort{}; + + template + using partial_sort_copy_result = copy_result<_Iter, _Out>; + + struct __partial_sort_copy_fn + { + template _Sent1, + random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_copyable<_Iter1, _Iter2> + && sortable<_Iter2, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>> + constexpr partial_sort_copy_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, + _Iter2 __result_first, _Sent2 __result_last, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if (__result_first == __result_last) + { + // TODO: Eliminating the variable __lasti triggers an ICE. + auto __lasti = ranges::next(std::move(__first), + std::move(__last)); + return {std::move(__lasti), std::move(__result_first)}; + } + + auto __result_real_last = __result_first; + while (__first != __last && __result_real_last != __result_last) + { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + + ranges::make_heap(__result_first, __result_real_last, __comp, __proj2); + for (; __first != __last; ++__first) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first), + std::__invoke(__proj2, *__result_first))) { - auto __left - = ranges::lower_bound(__first, __middle, - __value, __comp, __proj); - ranges::advance(__first, __len); - auto __right - = ranges::upper_bound(++__middle, __first, - __value, __comp, __proj); - return {__left, __right}; + ranges::pop_heap(__result_first, __result_real_last, + __comp, __proj2); + *(__result_real_last-1) = *__first; + ranges::push_heap(__result_first, __result_real_last, + __comp, __proj2); } - } - return {__first, __first}; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr safe_subrange_t<_Range> - equal_range(_Range&& __r, const _Tp& __value, - _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::equal_range(ranges::begin(__r), ranges::end(__r), - __value, + ranges::sort_heap(__result_first, __result_real_last, __comp, __proj2); + + return {std::move(__first), std::move(__result_real_last)}; + } + + template + requires indirectly_copyable, iterator_t<_Range2>> + && sortable, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected, _Proj1>, + projected, _Proj2>> + constexpr partial_sort_copy_result, + safe_iterator_t<_Range2>> + operator()(_Range1&& __r, _Range2&& __out, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + ranges::begin(__out), ranges::end(__out), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __partial_sort_copy_fn partial_sort_copy{}; + + struct __is_sorted_until_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return __next; + return __next; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_sorted_until_fn is_sorted_until{}; + + struct __is_sorted_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return true; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr bool - binary_search(_Iter __first, _Sent __last, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) - { - auto __i = ranges::lower_bound(__first, __last, __value, __comp, __proj); - if (__i == __last) - return false; - return !(bool)std::__invoke(__comp, __value, std::__invoke(__proj, *__i)); - } - - template, _Proj>> - _Comp = ranges::less> - constexpr bool - binary_search(_Range&& __r, const _Tp& __value, _Comp __comp = {}, - _Proj __proj = {}) - { - return ranges::binary_search(ranges::begin(__r), ranges::end(__r), + } + }; + + inline constexpr __is_sorted_fn is_sorted{}; + + struct __nth_element_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Iter __nth, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::nth_element(std::move(__first), std::move(__nth), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __nth, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__nth), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __nth_element_fn nth_element{}; + + struct __lower_bound_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, std::__invoke(__proj, *__middle), __value)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __lower_bound_fn lower_bound{}; + + struct __upper_bound_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, __value, std::__invoke(__proj, *__middle))) + __len = __half; + else + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), __value, std::move(__comp), std::move(__proj)); - } + } + }; - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr bool - is_partitioned(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - __first = ranges::find_if_not(std::move(__first), __last, __pred, __proj); - if (__first == __last) - return true; - ++__first; - return ranges::none_of(std::move(__first), std::move(__last), - std::move(__pred), std::move(__proj)); - } - - template, _Proj>> _Pred> - constexpr bool - is_partitioned(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::is_partitioned(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr subrange<_Iter> - partition(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - if constexpr (bidirectional_iterator<_Iter>) - { - auto __lasti = ranges::next(__first, __last); - auto __tail = __lasti; - for (;;) - { - for (;;) - if (__first == __tail) - return {std::move(__first), std::move(__lasti)}; - else if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - ++__first; - else - break; - --__tail; - for (;;) - if (__first == __tail) - return {std::move(__first), std::move(__lasti)}; - else if (!(bool)std::__invoke(__pred, - std::__invoke(__proj, *__tail))) - --__tail; - else - break; - ranges::iter_swap(__first, __tail); - ++__first; - } - } - else - { - if (__first == __last) - return {std::move(__first), std::move(__first)}; + inline constexpr __upper_bound_fn upper_bound{}; - while (std::__invoke(__pred, std::__invoke(__proj, *__first))) - if (++__first == __last) - return {std::move(__first), std::move(__first)}; + struct __equal_range_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); - auto __next = __first; - while (++__next != __last) - if (std::__invoke(__pred, std::__invoke(__proj, *__next))) + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, + std::__invoke(__proj, *__middle), + __value)) { - ranges::iter_swap(__first, __next); + __first = __middle; ++__first; + __len = __len - __half - 1; + } + else if (std::__invoke(__comp, + __value, + std::__invoke(__proj, *__middle))) + __len = __half; + else + { + auto __left + = ranges::lower_bound(__first, __middle, + __value, __comp, __proj); + ranges::advance(__first, __len); + auto __right + = ranges::upper_bound(++__middle, __first, + __value, __comp, __proj); + return {__left, __right}; } + } + return {__first, __first}; + } - return {std::move(__first), std::move(__next)}; - } - } + template, _Proj>> + _Comp = ranges::less> + constexpr safe_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, + std::move(__comp), std::move(__proj)); + } + }; - template, _Proj>> _Pred> - requires permutable> - constexpr safe_subrange_t<_Range> - partition(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::partition(ranges::begin(__r), ranges::end(__r), + inline constexpr __equal_range_fn equal_range{}; + + struct __binary_search_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __i = ranges::lower_bound(__first, __last, __value, __comp, __proj); + if (__i == __last) + return false; + return !(bool)std::__invoke(__comp, __value, std::__invoke(__proj, *__i)); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {}, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __binary_search_fn binary_search{}; + + struct __is_partitioned_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + __first = ranges::find_if_not(std::move(__first), __last, __pred, __proj); + if (__first == __last) + return true; + ++__first; + return ranges::none_of(std::move(__first), std::move(__last), std::move(__pred), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires permutable<_Iter> - subrange<_Iter> - stable_partition(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - auto __lasti = ranges::next(__first, __last); - auto __middle - = std::stable_partition(std::move(__first), __lasti, - __detail::__make_pred_proj(__pred, __proj)); - return {std::move(__middle), std::move(__lasti)}; - } - - template, _Proj>> _Pred> - requires permutable> - safe_subrange_t<_Range> - stable_partition(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::stable_partition(ranges::begin(__r), ranges::end(__r), + } + + template, _Proj>> _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__pred), std::move(__proj)); - } + } + }; + + inline constexpr __is_partitioned_fn is_partitioned{}; + + struct __partition_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + if constexpr (bidirectional_iterator<_Iter>) + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + for (;;) + { + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + else + break; + --__tail; + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (!(bool)std::__invoke(__pred, + std::__invoke(__proj, *__tail))) + --__tail; + else + break; + ranges::iter_swap(__first, __tail); + ++__first; + } + } + else + { + if (__first == __last) + return {std::move(__first), std::move(__first)}; + + while (std::__invoke(__pred, std::__invoke(__proj, *__first))) + if (++__first == __last) + return {std::move(__first), std::move(__first)}; + + auto __next = __first; + while (++__next != __last) + if (std::__invoke(__pred, std::__invoke(__proj, *__next))) + { + ranges::iter_swap(__first, __next); + ++__first; + } + + return {std::move(__first), std::move(__next)}; + } + } + + template, _Proj>> _Pred> + requires permutable> + constexpr safe_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_fn partition{}; + + struct __stable_partition_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires permutable<_Iter> + subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + auto __middle + = std::stable_partition(std::move(__first), __lasti, + __detail::__make_pred_proj(__pred, __proj)); + return {std::move(__middle), std::move(__lasti)}; + } + + template, _Proj>> _Pred> + requires permutable> + safe_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __stable_partition_fn stable_partition{}; template struct partition_copy_result @@ -2203,226 +2480,433 @@ namespace ranges { return {std::move(in), std::move(out1), std::move(out2)}; } }; - template _Sent, - weakly_incrementable _Out1, weakly_incrementable _O2, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_Iter, _Out1> - && indirectly_copyable<_Iter, _O2> - constexpr partition_copy_result<_Iter, _Out1, _O2> - partition_copy(_Iter __first, _Sent __last, - _Out1 __out_true, _O2 __out_false, - _Pred __pred, _Proj __proj = {}) - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + struct __partition_copy_fn + { + template _Sent, + weakly_incrementable _Out1, weakly_incrementable _O2, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out1> + && indirectly_copyable<_Iter, _O2> + constexpr partition_copy_result<_Iter, _Out1, _O2> + operator()(_Iter __first, _Sent __last, + _Out1 __out_true, _O2 __out_false, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__out_true = *__first; + ++__out_true; + } + else + { + *__out_false = *__first; + ++__out_false; + } + + return {std::move(__first), std::move(__out_true), std::move(__out_false)}; + } + + template, _Proj>> _Pred> + requires indirectly_copyable, _Out1> + && indirectly_copyable, _O2> + constexpr partition_copy_result, _Out1, _O2> + operator()(_Range&& __r, _Out1 out_true, _O2 out_false, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(out_true), std::move(out_false), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_copy_fn partition_copy{}; + + struct __partition_point_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) { - *__out_true = *__first; - ++__out_true; + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__pred, std::__invoke(__proj, *__middle))) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; } - else + return __first; + } + + template, _Proj>> _Pred> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_point_fn partition_point{}; + + template + using merge_result = binary_transform_result<_Iter1, _Iter2, _Out>; + + struct __merge_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr merge_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) { - *__out_false = *__first; - ++__out_false; + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + } + ++__result; } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out) }; + } - return {std::move(__first), std::move(__out_true), std::move(__out_false)}; - } - - template, _Proj>> _Pred> - requires indirectly_copyable, _Out1> - && indirectly_copyable, _O2> - constexpr partition_copy_result, _Out1, _O2> - partition_copy(_Range&& __r, _Out1 out_true, _O2 out_false, - _Pred __pred, _Proj __proj = {}) - { - return ranges::partition_copy(ranges::begin(__r), ranges::end(__r), - std::move(out_true), std::move(out_false), - std::move(__pred), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr _Iter - partition_point(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) - { - auto __len = ranges::distance(__first, __last); + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr merge_result, + safe_iterator_t<_Range2>, + _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; - while (__len > 0) - { - auto __half = __len / 2; - auto __middle = __first; - ranges::advance(__middle, __half); - if (std::__invoke(__pred, std::__invoke(__proj, *__middle))) - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - else - __len = __half; - } - return __first; - } + inline constexpr __merge_fn merge{}; - template, _Proj>> _Pred> - constexpr safe_iterator_t<_Range> - partition_point(_Range&& __r, _Pred __pred, _Proj __proj = {}) - { - return ranges::partition_point(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } + struct __inplace_merge_fn + { + template _Sent, + typename _Comp = ranges::less, + typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::inplace_merge(std::move(__first), std::move(__middle), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } - template - using merge_result = binary_transform_result<_Iter1, _Iter2, _Out>; + template + requires sortable, _Comp, _Proj> + safe_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr merge_result<_Iter1, _Iter2, _Out> - merge(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Out __result, - _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - while (__first1 != __last1 && __first2 != __last2) - { + inline constexpr __inplace_merge_fn inplace_merge{}; + + struct __includes_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) if (std::__invoke(__comp, std::__invoke(__proj2, *__first2), std::__invoke(__proj1, *__first1))) + return false; + else if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else { - *__result = *__first2; + ++__first1; ++__first2; } + + return __first2 == __last2; + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __includes_fn includes{}; + + template + using set_union_result = binary_transform_result<_Iter1, _Iter2, _Out>; + + struct __set_union_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_union_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_union_result, + safe_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_union_fn set_union{}; + + template + using set_intersection_result = binary_transform_result<_Iter1, _Iter2, _Out>; + + struct __set_intersection_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_intersection_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + ++__first2; else { *__result = *__first1; ++__first1; + ++__first2; + ++__result; } - ++__result; - } - auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), - std::move(__result)); - auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), - std::move(__copy1.out)); - return { std::move(__copy1.in), std::move(__copy2.in), - std::move(__copy2.out) }; - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr merge_result, - safe_iterator_t<_Range2>, - _Out> - merge(_Range1&& __r1, _Range2&& __r2, _Out __result, - _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::merge(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - - template _Sent, - typename _Comp = ranges::less, - typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - _Iter - inplace_merge(_Iter __first, _Iter __middle, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - auto __lasti = ranges::next(__first, __last); - std::inplace_merge(std::move(__first), std::move(__middle), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - safe_iterator_t<_Range> - inplace_merge(_Range&& __r, iterator_t<_Range> __middle, - _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::inplace_merge(ranges::begin(__r), std::move(__middle), - ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + // TODO: Eliminating these variables triggers an ICE. + auto __last1i = ranges::next(std::move(__first1), std::move(__last1)); + auto __last2i = ranges::next(std::move(__first2), std::move(__last2)); + return {std::move(__last1i), std::move(__last2i), std::move(__result)}; + } - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Proj1 = identity, typename _Proj2 = identity, - indirect_strict_weak_order, - projected<_Iter2, _Proj2>> - _Comp = ranges::less> - constexpr bool - includes(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - while (__first1 != __last1 && __first2 != __last2) - if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - return false; - else if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - ++__first1; - else - { - ++__first1; + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_intersection_result, + safe_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_intersection_fn set_intersection{}; + + template + using set_difference_result = copy_result<_Iter, _Out>; + + struct __set_difference_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_difference_result<_Iter1, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) ++__first2; - } + else + { + ++__first1; + ++__first2; + } + return ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + } - return __first2 == __last2; - } + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_difference_result, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; - template, _Proj1>, - projected, _Proj2>> - _Comp = ranges::less> - constexpr bool - includes(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::includes(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } + inline constexpr __set_difference_fn set_difference{}; template - using set_union_result = binary_transform_result<_Iter1, _Iter2, _Out>; + using set_symmetric_difference_result + = binary_transform_result<_Iter1, _Iter2, _Out>; - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr set_union_result<_Iter1, _Iter2, _Out> - set_union(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Out __result, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - while (__first1 != __last1 && __first2 != __last2) - { + struct __set_symmetric_difference_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) if (std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) { *__result = *__first1; ++__first1; + ++__result; } else if (std::__invoke(__comp, std::__invoke(__proj2, *__first2), @@ -2430,298 +2914,146 @@ namespace ranges { *__result = *__first2; ++__first2; + ++__result; } else { - *__result = *__first1; ++__first1; ++__first2; } - ++__result; - } - auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), - std::move(__result)); - auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), - std::move(__copy1.out)); - return {std::move(__copy1.in), std::move(__copy2.in), - std::move(__copy2.out)}; - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr set_union_result, - safe_iterator_t<_Range2>, _Out> - set_union(_Range1&& __r1, _Range2&& __r2, _Out __result, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::set_union(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } - template - using set_intersection_result = binary_transform_result<_Iter1, _Iter2, _Out>; + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result, + safe_iterator_t<_Range2>, + _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this) + (ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr set_intersection_result<_Iter1, _Iter2, _Out> - set_intersection(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Out __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - while (__first1 != __last1 && __first2 != __last2) - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - ++__first1; - else if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - ++__first2; + inline constexpr __set_symmetric_difference_fn set_symmetric_difference{}; + + struct __min_fn + { + template> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return __b; else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) { - *__result = *__first1; - ++__first1; - ++__first2; - ++__result; + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result))) + __result = std::move(__tmp); } - // TODO: Eliminating these variables triggers an ICE. - auto __last1i = ranges::next(std::move(__first1), std::move(__last1)); - auto __last2i = ranges::next(std::move(__first2), std::move(__last2)); - return {std::move(__last1i), std::move(__last2i), std::move(__result)}; - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr set_intersection_result, - safe_iterator_t<_Range2>, _Out> - set_intersection(_Range1&& __r1, _Range2&& __r2, _Out __result, - _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::set_intersection(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } + return __result; + } - template - using set_difference_result = copy_result<_Iter, _Out>; + template> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr set_difference_result<_Iter1, _Out> - set_difference(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Out __result, - _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - while (__first1 != __last1 && __first2 != __last2) - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - { - *__result = *__first1; - ++__first1; - ++__result; - } - else if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - ++__first2; + inline constexpr __min_fn min{}; + + struct __max_fn + { + template> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __a), + std::__invoke(__proj, __b))) + return __b; else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) { - ++__first1; - ++__first2; + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __result), + std::__invoke(__proj, __tmp))) + __result = std::move(__tmp); } - return ranges::copy(std::move(__first1), std::move(__last1), - std::move(__result)); - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr set_difference_result, _Out> - set_difference(_Range1&& __r1, _Range2&& __r2, _Out __result, - _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::set_difference(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } + return __result; + } - template - using set_symmetric_difference_result - = binary_transform_result<_Iter1, _Iter2, _Out>; + template> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr set_symmetric_difference_result<_Iter1, _Iter2, _Out> - set_symmetric_difference(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Out __result, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - while (__first1 != __last1 && __first2 != __last2) - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - { - *__result = *__first1; - ++__first1; - ++__result; - } - else if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - { - *__result = *__first2; - ++__first2; - ++__result; - } - else - { - ++__first1; - ++__first2; - } - auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), - std::move(__result)); - auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), - std::move(__copy1.out)); - return {std::move(__copy1.in), std::move(__copy2.in), - std::move(__copy2.out)}; - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr set_symmetric_difference_result, - safe_iterator_t<_Range2>, - _Out> - set_symmetric_difference(_Range1&& __r1, _Range2&& __r2, _Out __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return (ranges::set_symmetric_difference - (ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2))); - } - - template> - _Comp = ranges::less> - constexpr const _Tp& - min(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) - { - if (std::__invoke(std::move(__comp), - std::__invoke(__proj, __b), - std::__invoke(__proj, __a))) - return __b; - else - return __a; - } - - template, _Proj>> - _Comp = ranges::less> - requires indirectly_copyable_storable, - range_value_t<_Range>*> - constexpr range_value_t<_Range> - min(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - __glibcxx_assert(__first != __last); - auto __result = *__first; - while (++__first != __last) - { - auto __tmp = *__first; - if (std::__invoke(__comp, - std::__invoke(__proj, __tmp), - std::__invoke(__proj, __result))) - __result = std::move(__tmp); - } - return __result; - } - - template> - _Comp = ranges::less> - constexpr _Tp - min(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::min(ranges::subrange(__r), - std::move(__comp), std::move(__proj)); - } - - template> - _Comp = ranges::less> - constexpr const _Tp& - max(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) - { - if (std::__invoke(std::move(__comp), - std::__invoke(__proj, __a), - std::__invoke(__proj, __b))) - return __b; - else - return __a; - } - - template, _Proj>> - _Comp = ranges::less> - requires indirectly_copyable_storable, - range_value_t<_Range>*> - constexpr range_value_t<_Range> - max(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - __glibcxx_assert(__first != __last); - auto __result = *__first; - while (++__first != __last) - { - auto __tmp = *__first; - if (std::__invoke(__comp, - std::__invoke(__proj, __result), - std::__invoke(__proj, __tmp))) - __result = std::move(__tmp); - } - return __result; - } - - template> - _Comp = ranges::less> - constexpr _Tp - max(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::max(ranges::subrange(__r), - std::move(__comp), std::move(__proj)); - } + inline constexpr __max_fn max{}; template struct minmax_result @@ -2740,258 +3072,283 @@ namespace ranges { return {std::move(min), std::move(max)}; } }; - template> - _Comp = ranges::less> - constexpr minmax_result - minmax(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) - { - if (std::__invoke(std::move(__comp), - std::__invoke(__proj, __b), - std::__invoke(__proj, __a))) - return {__b, __a}; - else - return {__a, __b}; - } - - template, _Proj>> - _Comp = ranges::less> - requires indirectly_copyable_storable, - range_value_t<_Range>*> - constexpr minmax_result> - minmax(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - __glibcxx_assert(__first != __last); - minmax_result> __result = {*__first, *__first}; - while (++__first != __last) - { - auto __tmp = *__first; - if (std::__invoke(__comp, - std::__invoke(__proj, __tmp), - std::__invoke(__proj, __result.min))) - __result.min = std::move(__tmp); - if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, __tmp), - std::__invoke(__proj, __result.max))) - __result.max = std::move(__tmp); - } - return __result; - } - - template> - _Comp = ranges::less> - constexpr minmax_result<_Tp> - minmax(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::minmax(ranges::subrange(__r), - std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - min_element(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - if (__first == __last) + struct __minmax_fn + { + template> + _Comp = ranges::less> + constexpr minmax_result + operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return {__b, __a}; + else + return {__a, __b}; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr minmax_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + minmax_result> __result = {*__first, *__first}; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result.min))) + __result.min = std::move(__tmp); + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result.max))) + __result.max = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr minmax_result<_Tp> + operator()(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __minmax_fn minmax{}; + + struct __min_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) + __first = __i; + } return __first; + } - auto __i = __first; - while (++__i != __last) - { - if (std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__first))) - __first = __i; - } - return __first; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr safe_iterator_t<_Range> - min_element(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::min_element(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - max_element(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - if (__first == __last) + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __min_element_fn min_element{}; + + struct __max_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__i))) + __first = __i; + } return __first; + } - auto __i = __first; - while (++__i != __last) - { - if (std::__invoke(__comp, - std::__invoke(__proj, *__first), - std::__invoke(__proj, *__i))) - __first = __i; - } - return __first; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr safe_iterator_t<_Range> - max_element(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::max_element(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __max_element_fn max_element{}; template using minmax_element_result = minmax_result<_Iter>; - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr minmax_element_result<_Iter> - minmax_element(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - if (__first == __last) - return {__first, __first}; + struct __minmax_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr minmax_element_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {__first, __first}; - minmax_element_result<_Iter> __result = {__first, __first}; - auto __i = __first; - while (++__i != __last) - { - if (std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__result.min))) - __result.min = __i; - if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__result.max))) - __result.max = __i; - } - return __result; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr minmax_element_result> - minmax_element(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::minmax_element(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + minmax_element_result<_Iter> __result = {__first, __first}; + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__result.min))) + __result.min = __i; + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__result.max))) + __result.max = __i; + } + return __result; + } - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Proj1 = identity, typename _Proj2 = identity, - indirect_strict_weak_order, - projected<_Iter2, _Proj2>> - _Comp = ranges::less> - constexpr bool - lexicographical_compare(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - if constexpr (__detail::__is_normal_iterator<_Iter1> - || __detail::__is_normal_iterator<_Iter2>) - return ranges::lexicographical_compare - (std::__niter_base(std::move(__first1)), - std::__niter_base(std::move(__last1)), - std::__niter_base(std::move(__first2)), - std::__niter_base(std::move(__last2)), - std::move(__comp), - std::move(__proj1), std::move(__proj2)); - - constexpr bool __sized_iters - = (sized_sentinel_for<_Sent1, _Iter1> - && sized_sentinel_for<_Sent2, _Iter2>); - if constexpr (__sized_iters) - { - auto __d1 = ranges::distance(__first1, __last1); - auto __d2 = ranges::distance(__first2, __last2); - - using _ValueType1 = iter_value_t<_Iter1>; - using _ValueType2 = iter_value_t<_Iter2>; - constexpr bool __use_memcmp - = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) - && is_same_v<_ValueType1, _ValueType2> - && is_pointer_v<_Iter1> - && is_pointer_v<_Iter2> - && (is_same_v<_Comp, ranges::less> - || is_same_v<_Comp, ranges::greater>) - && is_same_v<_Proj1, identity> - && is_same_v<_Proj2, identity>); - if constexpr (__use_memcmp) - { - if (const auto __len = std::min(__d1, __d2)) - { - const auto __c = std::__memcmp(__first1, __first2, __len); - if constexpr (is_same_v<_Comp, ranges::less>) - { - if (__c < 0) - return true; - if (__c > 0) - return false; - } - else if constexpr (is_same_v<_Comp, ranges::greater>) - { - if (__c > 0) - return true; - if (__c < 0) - return false; - } - else - __builtin_unreachable(); - } - return (__last1 - __first1 < __last2 - __first2); - } - } + template, _Proj>> + _Comp = ranges::less> + constexpr minmax_element_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void) ++__first2) - { - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - return true; - if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - return false; - } - return __first1 == __last1 && __first2 != __last2; - } + inline constexpr __minmax_element_fn minmax_element{}; - template, _Proj1>, - projected, _Proj2>> - _Comp = ranges::less> - constexpr bool - lexicographical_compare(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return (ranges::lexicographical_compare - (ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__comp), - std::move(__proj1), std::move(__proj2))); - } + struct __lexicographical_compare_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if constexpr (__detail::__is_normal_iterator<_Iter1> + || __detail::__is_normal_iterator<_Iter2>) + return (*this) + (std::__niter_base(std::move(__first1)), + std::__niter_base(std::move(__last1)), + std::__niter_base(std::move(__first2)), + std::__niter_base(std::move(__last2)), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + + using _ValueType1 = iter_value_t<_Iter1>; + using _ValueType2 = iter_value_t<_Iter2>; + constexpr bool __use_memcmp + = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) + && is_same_v<_ValueType1, _ValueType2> + && is_pointer_v<_Iter1> + && is_pointer_v<_Iter2> + && (is_same_v<_Comp, ranges::less> + || is_same_v<_Comp, ranges::greater>) + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + if (const auto __len = std::min(__d1, __d2)) + { + const auto __c = std::__memcmp(__first1, __first2, __len); + if constexpr (is_same_v<_Comp, ranges::less>) + { + if (__c < 0) + return true; + if (__c > 0) + return false; + } + else if constexpr (is_same_v<_Comp, ranges::greater>) + { + if (__c > 0) + return true; + if (__c < 0) + return false; + } + else + __builtin_unreachable(); + } + return (__last1 - __first1 < __last2 - __first2); + } + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void) ++__first2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return true; + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this) + (ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __lexicographical_compare_fn lexicographical_compare; template struct next_permutation_result @@ -3000,116 +3357,126 @@ namespace ranges _Iter in; }; - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr next_permutation_result<_Iter> - next_permutation(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - if (__first == __last) - return {false, std::move(__first)}; + struct __next_permutation_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr next_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {false, std::move(__first)}; - auto __i = __first; - ++__i; - if (__i == __last) - return {false, std::move(__i)}; + auto __i = __first; + ++__i; + if (__i == __last) + return {false, std::move(__i)}; - auto __lasti = ranges::next(__first, __last); - __i = __lasti; - --__i; + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; - for (;;) - { - auto __ii = __i; - --__i; - if (std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__ii))) - { - auto __j = __lasti; - while (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *--__j))) - ; - ranges::iter_swap(__i, __j); - ranges::reverse(__ii, __last); - return {true, std::move(__lasti)}; - } - if (__i == __first) - { - ranges::reverse(__first, __last); - return {false, std::move(__lasti)}; - } - } - } + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__ii))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *--__j))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {true, std::move(__lasti)}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {false, std::move(__lasti)}; + } + } + } - template - requires sortable, _Comp, _Proj> - constexpr next_permutation_result> - next_permutation(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::next_permutation(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + template + requires sortable, _Comp, _Proj> + constexpr next_permutation_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __next_permutation_fn next_permutation{}; template using prev_permutation_result = next_permutation_result<_Iter>; - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr prev_permutation_result<_Iter> - prev_permutation(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) - { - if (__first == __last) - return {false, std::move(__first)}; + struct __prev_permutation_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr prev_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {false, std::move(__first)}; - auto __i = __first; - ++__i; - if (__i == __last) - return {false, std::move(__i)}; + auto __i = __first; + ++__i; + if (__i == __last) + return {false, std::move(__i)}; - auto __lasti = ranges::next(__first, __last); - __i = __lasti; - --__i; + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; - for (;;) - { - auto __ii = __i; - --__i; - if (std::__invoke(__comp, - std::__invoke(__proj, *__ii), - std::__invoke(__proj, *__i))) - { - auto __j = __lasti; - while (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *--__j), - std::__invoke(__proj, *__i))) - ; - ranges::iter_swap(__i, __j); - ranges::reverse(__ii, __last); - return {true, std::move(__lasti)}; - } - if (__i == __first) - { - ranges::reverse(__first, __last); - return {false, std::move(__lasti)}; - } - } - } + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__ii), + std::__invoke(__proj, *__i))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *--__j), + std::__invoke(__proj, *__i))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {true, std::move(__lasti)}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {false, std::move(__lasti)}; + } + } + } - template - requires sortable, _Comp, _Proj> - constexpr prev_permutation_result> - prev_permutation(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) - { - return ranges::prev_permutation(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } + template + requires sortable, _Comp, _Proj> + constexpr prev_permutation_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __prev_permutation_fn prev_permutation{}; } // namespace ranges _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index 813a5096ae0..f3b800863dc 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -71,88 +71,93 @@ namespace ranges __is_move_iterator> = true; } // namespace __detail - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr bool - equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - // TODO: implement more specializations to at least have parity with - // std::equal. - if constexpr (__detail::__is_normal_iterator<_Iter1> - || __detail::__is_normal_iterator<_Iter2>) - return ranges::equal(std::__niter_base(std::move(__first1)), - std::__niter_base(std::move(__last1)), - std::__niter_base(std::move(__first2)), - std::__niter_base(std::move(__last2)), + struct __equal_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + // TODO: implement more specializations to at least have parity with + // std::equal. + if constexpr (__detail::__is_normal_iterator<_Iter1> + || __detail::__is_normal_iterator<_Iter2>) + return (*this)(std::__niter_base(std::move(__first1)), + std::__niter_base(std::move(__last1)), + std::__niter_base(std::move(__first2)), + std::__niter_base(std::move(__last2)), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + + using _ValueType1 = iter_value_t<_Iter1>; + using _ValueType2 = iter_value_t<_Iter2>; + constexpr bool __use_memcmp + = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) + && is_same_v<_ValueType1, _ValueType2> + && is_pointer_v<_Iter1> + && is_pointer_v<_Iter2> + && is_same_v<_Pred, ranges::equal_to> + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + if (const size_t __len = (__last1 - __first1)) + return !std::__memcmp(__first1, __first2, __len); + return true; + } + else + { + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return true; + } + } + else + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return __first1 == __last1 && __first2 == __last2; + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), std::move(__pred), std::move(__proj1), std::move(__proj2)); + } + }; - constexpr bool __sized_iters - = (sized_sentinel_for<_Sent1, _Iter1> - && sized_sentinel_for<_Sent2, _Iter2>); - if constexpr (__sized_iters) - { - auto __d1 = ranges::distance(__first1, __last1); - auto __d2 = ranges::distance(__first2, __last2); - if (__d1 != __d2) - return false; - - using _ValueType1 = iter_value_t<_Iter1>; - using _ValueType2 = iter_value_t<_Iter2>; - constexpr bool __use_memcmp - = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) - && is_same_v<_ValueType1, _ValueType2> - && is_pointer_v<_Iter1> - && is_pointer_v<_Iter2> - && is_same_v<_Pred, ranges::equal_to> - && is_same_v<_Proj1, identity> - && is_same_v<_Proj2, identity>); - if constexpr (__use_memcmp) - { - if (const size_t __len = (__last1 - __first1)) - return !std::__memcmp(__first1, __first2, __len); - return true; - } - else - { - for (; __first1 != __last1; ++__first1, (void)++__first2) - if (!(bool)std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - return false; - return true; - } - } - else - { - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - if (!(bool)std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - return false; - return __first1 == __last1 && __first2 == __last2; - } - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr bool - equal(_Range1&& __r1, _Range2&& __r2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - return ranges::equal(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } + inline constexpr __equal_fn equal{}; template struct copy_result @@ -288,45 +293,55 @@ namespace ranges } } - template _Sent, - weakly_incrementable _Out> - requires indirectly_copyable<_Iter, _Out> - constexpr copy_result<_Iter, _Out> - copy(_Iter __first, _Sent __last, _Out __result) - { - return ranges::__copy_or_move(std::move(__first), - std::move(__last), - std::move(__result)); - } - - template - requires indirectly_copyable, _Out> - constexpr copy_result, _Out> - copy(_Range&& __r, _Out __result) - { - return ranges::copy(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } - - template _Sent, - weakly_incrementable _Out> - requires indirectly_movable<_Iter, _Out> - constexpr move_result<_Iter, _Out> - move(_Iter __first, _Sent __last, _Out __result) - { - return ranges::__copy_or_move(std::move(__first), - std::move(__last), - std::move(__result)); - } - - template - requires indirectly_movable, _Out> - constexpr move_result, _Out> - move(_Range&& __r, _Out __result) - { - return ranges::move(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } + struct __copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Out> + constexpr copy_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __copy_fn copy{}; + + struct __move_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_movable<_Iter, _Out> + constexpr move_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Out> + constexpr move_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __move_fn move{}; template _Sent, @@ -420,127 +435,152 @@ namespace ranges } } - template _Sent1, - bidirectional_iterator _Iter2> - requires indirectly_copyable<_Iter1, _Iter2> - constexpr copy_backward_result<_Iter1, _Iter2> - copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) - { - return ranges::__copy_or_move_backward(std::move(__first), - std::move(__last), - std::move(__result)); - } - - template - requires indirectly_copyable, _Iter> - constexpr copy_backward_result, _Iter> - copy_backward(_Range&& __r, _Iter __result) - { - return ranges::copy_backward(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } - - template _Sent1, - bidirectional_iterator _Iter2> - requires indirectly_movable<_Iter1, _Iter2> - constexpr move_backward_result<_Iter1, _Iter2> - move_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) - { - return ranges::__copy_or_move_backward(std::move(__first), - std::move(__last), - std::move(__result)); - } - - template - requires indirectly_movable, _Iter> - constexpr move_backward_result, _Iter> - move_backward(_Range&& __r, _Iter __result) - { - return ranges::move_backward(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } + struct __copy_backward_fn + { + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_copyable<_Iter1, _Iter2> + constexpr copy_backward_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Iter> + constexpr copy_backward_result, _Iter> + operator()(_Range&& __r, _Iter __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __copy_backward_fn copy_backward{}; + + struct __move_backward_fn + { + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_movable<_Iter1, _Iter2> + constexpr move_backward_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Iter> + constexpr move_backward_result, _Iter> + operator()(_Range&& __r, _Iter __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __move_backward_fn move_backward{}; template using copy_n_result = copy_result<_Iter, _Out>; - template - requires indirectly_copyable<_Iter, _Out> - constexpr copy_n_result<_Iter, _Out> - copy_n(_Iter __first, iter_difference_t<_Iter> __n, _Out __result) - { - if constexpr (random_access_iterator<_Iter>) - return ranges::copy(__first, __first + __n, std::move(__result)); - else - { - for (; __n > 0; --__n, (void)++__result, (void)++__first) - *__result = *__first; - return {std::move(__first), std::move(__result)}; - } - } - - template _Out> - constexpr _Out - fill_n(_Out __first, iter_difference_t<_Out> __n, const _Tp& __value) - { - // TODO: implement more specializations to be at least on par with - // std::fill_n - if (__n <= 0) - return __first; - - // TODO: is __is_byte the best condition? - if constexpr (is_pointer_v<_Out> && __is_byte<_Tp>::__value) - { - __builtin_memset(__first, static_cast(__value), __n); - return __first + __n; - } - else if constexpr (is_scalar_v<_Tp>) - { - const auto __tmp = __value; - for (; __n > 0; --__n, (void)++__first) - *__first = __tmp; - return __first; - } - else - { - for (; __n > 0; --__n, (void)++__first) - *__first = __value; - return __first; - } - } - - template _Out, sentinel_for<_Out> _Sent> - constexpr _Out - fill(_Out __first, _Sent __last, const _Tp& __value) - { - // TODO: implement more specializations to be at least on par with - // std::fill - if constexpr (sized_sentinel_for<_Sent, _Out>) - { - const auto __len = __last - __first; - return ranges::fill_n(__first, __len, __value); - } - else if constexpr (is_scalar_v<_Tp>) - { - const auto __tmp = __value; - for (; __first != __last; ++__first) - *__first = __tmp; - return __first; - } - else - { - for (; __first != __last; ++__first) - *__first = __value; + struct __copy_n_fn + { + template + requires indirectly_copyable<_Iter, _Out> + constexpr copy_n_result<_Iter, _Out> + operator()(_Iter __first, iter_difference_t<_Iter> __n, _Out __result) const + { + if constexpr (random_access_iterator<_Iter>) + return ranges::copy(__first, __first + __n, std::move(__result)); + else + { + for (; __n > 0; --__n, (void)++__result, (void)++__first) + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + } + }; + + inline constexpr __copy_n_fn copy_n{}; + + struct __fill_n_fn + { + template _Out> + constexpr _Out + operator()(_Out __first, iter_difference_t<_Out> __n, const _Tp& __value) const + { + // TODO: implement more specializations to be at least on par with + // std::fill_n + if (__n <= 0) return __first; - } - } - template _Range> - constexpr safe_iterator_t<_Range> - fill(_Range&& __r, const _Tp& __value) - { - return ranges::fill(ranges::begin(__r), ranges::end(__r), __value); - } + // TODO: is __is_byte the best condition? + if constexpr (is_pointer_v<_Out> && __is_byte<_Tp>::__value) + { + __builtin_memset(__first, static_cast(__value), __n); + return __first + __n; + } + else if constexpr (is_scalar_v<_Tp>) + { + const auto __tmp = __value; + for (; __n > 0; --__n, (void)++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __n > 0; --__n, (void)++__first) + *__first = __value; + return __first; + } + } + }; + + inline constexpr __fill_n_fn fill_n{}; + + struct __fill_fn + { + template _Out, sentinel_for<_Out> _Sent> + constexpr _Out + operator()(_Out __first, _Sent __last, const _Tp& __value) const + { + // TODO: implement more specializations to be at least on par with + // std::fill + if constexpr (sized_sentinel_for<_Sent, _Out>) + { + const auto __len = __last - __first; + return ranges::fill_n(__first, __len, __value); + } + else if constexpr (is_scalar_v<_Tp>) + { + const auto __tmp = __value; + for (; __first != __last; ++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __first != __last; ++__first) + *__first = __value; + return __first; + } + } + + template _Range> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __value) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), __value); + } + }; + + inline constexpr __fill_fn fill{}; } _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/ranges_uninitialized.h b/libstdc++-v3/include/bits/ranges_uninitialized.h index 5ff2eaa1b3a..fa4238b9181 100644 --- a/libstdc++-v3/include/bits/ranges_uninitialized.h +++ b/libstdc++-v3/include/bits/ranges_uninitialized.h @@ -78,11 +78,21 @@ namespace ranges && __nothrow_forward_iterator>); } // namespace __detail - template<__detail::__nothrow_input_iterator _Iter, - __detail::__nothrow_sentinel<_Iter> _Sent> - requires destructible> - constexpr _Iter - destroy(_Iter __first, _Sent __last) noexcept; + struct __destroy_fn + { + template<__detail::__nothrow_input_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires destructible> + constexpr _Iter + operator()(_Iter __first, _Sent __last) const noexcept; + + template<__detail::__nothrow_input_range _Range> + requires destructible> + constexpr safe_iterator_t<_Range> + operator()(_Range&& __r) const noexcept; + }; + + inline constexpr __destroy_fn destroy{}; namespace __detail { @@ -126,332 +136,396 @@ namespace ranges }; } // namespace __detail - template<__detail::__nothrow_forward_iterator _Iter, - __detail::__nothrow_sentinel<_Iter> _Sent> - requires default_initializable> - _Iter - uninitialized_default_construct(_Iter __first, _Sent __last) - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivially_default_constructible_v<_ValueType>) - return ranges::next(__first, __last); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __first != __last; ++__first) - ::new (__detail::__voidify(*__first)) _ValueType; - __guard.release(); - return __first; - } - } + struct __uninitialized_default_construct_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires default_initializable> + _Iter + operator()(_Iter __first, _Sent __last) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivially_default_constructible_v<_ValueType>) + return ranges::next(__first, __last); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType; + __guard.release(); + return __first; + } + } - template<__detail::__nothrow_forward_range _Range> - requires default_initializable> - safe_iterator_t<_Range> - uninitialized_default_construct(_Range&& __r) - { - return ranges::uninitialized_default_construct(ranges::begin(__r), - ranges::end(__r)); - } + template<__detail::__nothrow_forward_range _Range> + requires default_initializable> + safe_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), + ranges::end(__r)); + } + }; - template<__detail::__nothrow_forward_iterator _Iter> - requires default_initializable> - _Iter - uninitialized_default_construct_n(_Iter __first, - iter_difference_t<_Iter> __n) - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivially_default_constructible_v<_ValueType>) - return ranges::next(__first, __n); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __n > 0; ++__first, (void) --__n) - ::new (__detail::__voidify(*__first)) _ValueType; - __guard.release(); - return __first; - } - } + inline constexpr __uninitialized_default_construct_fn + uninitialized_default_construct{}; - template<__detail::__nothrow_forward_iterator _Iter, - __detail::__nothrow_sentinel<_Iter> _Sent> - requires default_initializable> - _Iter - uninitialized_value_construct(_Iter __first, _Sent __last) - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivial_v<_ValueType> - && is_copy_assignable_v<_ValueType>) - return ranges::fill(__first, __last, _ValueType()); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __first != __last; ++__first) - ::new (__detail::__voidify(*__first)) _ValueType(); - __guard.release(); - return __first; - } - } + struct __uninitialized_default_construct_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter> + requires default_initializable> + _Iter + operator()(_Iter __first, + iter_difference_t<_Iter> __n) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivially_default_constructible_v<_ValueType>) + return ranges::next(__first, __n); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __n > 0; ++__first, (void) --__n) + ::new (__detail::__voidify(*__first)) _ValueType; + __guard.release(); + return __first; + } + } + }; - template<__detail::__nothrow_forward_range _Range> - requires default_initializable> - safe_iterator_t<_Range> - uninitialized_value_construct(_Range&& __r) - { - return ranges::uninitialized_value_construct(ranges::begin(__r), - ranges::end(__r)); - } + inline constexpr __uninitialized_default_construct_n_fn + uninitialized_default_construct_n; - template<__detail::__nothrow_forward_iterator _Iter> - requires default_initializable> - _Iter - uninitialized_value_construct_n(_Iter __first, iter_difference_t<_Iter> __n) - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivial_v<_ValueType> - && is_copy_assignable_v<_ValueType>) - return ranges::fill_n(__first, __n, _ValueType()); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __n > 0; ++__first, (void) --__n) - ::new (__detail::__voidify(*__first)) _ValueType(); - __guard.release(); - return __first; - } - } + struct __uninitialized_value_construct_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires default_initializable> + _Iter + operator()(_Iter __first, _Sent __last) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_copy_assignable_v<_ValueType>) + return ranges::fill(__first, __last, _ValueType()); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType(); + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range> + requires default_initializable> + safe_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), + ranges::end(__r)); + } + }; + + inline constexpr __uninitialized_value_construct_fn + uninitialized_value_construct{}; + + struct __uninitialized_value_construct_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter> + requires default_initializable> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_copy_assignable_v<_ValueType>) + return ranges::fill_n(__first, __n, _ValueType()); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __n > 0; ++__first, (void) --__n) + ::new (__detail::__voidify(*__first)) _ValueType(); + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_value_construct_n_fn + uninitialized_value_construct_n; template using uninitialized_copy_result = copy_result<_Iter, _Out>; - template _ISent, - __detail::__nothrow_forward_iterator _Out, - __detail::__nothrow_sentinel<_Out> _OSent> - requires constructible_from, iter_reference_t<_Iter>> - uninitialized_copy_result<_Iter, _Out> - uninitialized_copy(_Iter __ifirst, _ISent __ilast, - _Out __ofirst, _OSent __olast) - { - using _OutType = remove_reference_t>; - if constexpr (sized_sentinel_for<_ISent, _Iter> - && sized_sentinel_for<_OSent, _Out> - && is_trivial_v<_OutType> - && is_nothrow_assignable_v<_OutType, - iter_reference_t<_Iter>>) - { - auto __d1 = ranges::distance(__ifirst, __ilast); - auto __d2 = ranges::distance(__ofirst, __olast); - return ranges::copy_n(__ifirst, std::min(__d1, __d2), __ofirst); - } - else - { - auto __guard = __detail::_DestroyGuard(&__ofirst); - for (; __ifirst != __ilast && __ofirst != __olast; - ++__ofirst, (void)++__ifirst) - ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); - __guard.release(); - return {__ifirst, __ofirst}; - } - } + struct __uninitialized_copy_fn + { + template _ISent, + __detail::__nothrow_forward_iterator _Out, + __detail::__nothrow_sentinel<_Out> _OSent> + requires constructible_from, iter_reference_t<_Iter>> + uninitialized_copy_result<_Iter, _Out> + operator()(_Iter __ifirst, _ISent __ilast, + _Out __ofirst, _OSent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_ISent, _Iter> + && sized_sentinel_for<_OSent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType, + iter_reference_t<_Iter>>) + { + auto __d1 = ranges::distance(__ifirst, __ilast); + auto __d2 = ranges::distance(__ofirst, __olast); + return ranges::copy_n(__ifirst, std::min(__d1, __d2), __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __ifirst != __ilast && __ofirst != __olast; + ++__ofirst, (void)++__ifirst) + ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); + __guard.release(); + return {__ifirst, __ofirst}; + } + } - template - requires constructible_from, - range_reference_t<_IRange>> - uninitialized_copy_result, - safe_iterator_t<_ORange>> - uninitialized_copy(_IRange&& __inr, _ORange&& __outr) - { - return ranges::uninitialized_copy(ranges::begin(__inr), - ranges::end(__inr), - ranges::begin(__outr), - ranges::end(__outr)); - } + template + requires constructible_from, + range_reference_t<_IRange>> + uninitialized_copy_result, + safe_iterator_t<_ORange>> + operator()(_IRange&& __inr, _ORange&& __outr) const + { + return (*this)(ranges::begin(__inr), + ranges::end(__inr), + ranges::begin(__outr), + ranges::end(__outr)); + } + }; + + inline constexpr __uninitialized_copy_fn uninitialized_copy{}; template using uninitialized_copy_n_result = uninitialized_copy_result<_Iter, _Out>; + struct __uninitialized_copy_n_fn + { template _Sent> - requires constructible_from, iter_reference_t<_Iter>> - uninitialized_copy_n_result<_Iter, _Out> - uninitialized_copy_n(_Iter __ifirst, iter_difference_t<_Iter> __n, - _Out __ofirst, _Sent __olast) - { - using _OutType = remove_reference_t>; - if constexpr (sized_sentinel_for<_Sent, _Out> - && is_trivial_v<_OutType> - && is_nothrow_assignable_v<_OutType, - iter_reference_t<_Iter>>) - { - auto __d = ranges::distance(__ofirst, __olast); - return ranges::copy_n(__ifirst, std::min(__n, __d), __ofirst); - } - else - { - auto __guard = __detail::_DestroyGuard(&__ofirst); - for (; __n > 0 && __ofirst != __olast; - ++__ofirst, (void)++__ifirst, (void)--__n) - ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); - __guard.release(); - return {__ifirst, __ofirst}; - } - } + __detail::__nothrow_sentinel<_Out> _Sent> + requires constructible_from, iter_reference_t<_Iter>> + uninitialized_copy_n_result<_Iter, _Out> + operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, + _Out __ofirst, _Sent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_Sent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType, + iter_reference_t<_Iter>>) + { + auto __d = ranges::distance(__ofirst, __olast); + return ranges::copy_n(__ifirst, std::min(__n, __d), __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __n > 0 && __ofirst != __olast; + ++__ofirst, (void)++__ifirst, (void)--__n) + ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); + __guard.release(); + return {__ifirst, __ofirst}; + } + } + }; + + inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{}; template using uninitialized_move_result = uninitialized_copy_result<_Iter, _Out>; - template _ISent, - __detail::__nothrow_forward_iterator _Out, - __detail::__nothrow_sentinel<_Out> _OSent> - requires constructible_from, - iter_rvalue_reference_t<_Iter>> - uninitialized_move_result<_Iter, _Out> - uninitialized_move(_Iter __ifirst, _ISent __ilast, - _Out __ofirst, _OSent __olast) - { - using _OutType = remove_reference_t>; - if constexpr (sized_sentinel_for<_ISent, _Iter> - && sized_sentinel_for<_OSent, _Out> - && is_trivial_v<_OutType> - && is_nothrow_assignable_v<_OutType, - iter_rvalue_reference_t<_Iter>>) - { - auto __d1 = ranges::distance(__ifirst, __ilast); - auto __d2 = ranges::distance(__ofirst, __olast); - return ranges::copy_n(std::make_move_iterator(__ifirst), - std::min(__d1, __d2), __ofirst); - } - else - { - auto __guard = __detail::_DestroyGuard(&__ofirst); - for (; __ifirst != __ilast && __ofirst != __olast; - ++__ofirst, (void)++__ifirst) - ::new (__detail::__voidify(*__ofirst)) - _OutType(ranges::iter_move(__ifirst)); - __guard.release(); - return {__ifirst, __ofirst}; - } - } + struct __uninitialized_move_fn + { + template _ISent, + __detail::__nothrow_forward_iterator _Out, + __detail::__nothrow_sentinel<_Out> _OSent> + requires constructible_from, + iter_rvalue_reference_t<_Iter>> + uninitialized_move_result<_Iter, _Out> + operator()(_Iter __ifirst, _ISent __ilast, + _Out __ofirst, _OSent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_ISent, _Iter> + && sized_sentinel_for<_OSent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType, + iter_rvalue_reference_t<_Iter>>) + { + auto __d1 = ranges::distance(__ifirst, __ilast); + auto __d2 = ranges::distance(__ofirst, __olast); + return ranges::copy_n(std::make_move_iterator(__ifirst), + std::min(__d1, __d2), __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __ifirst != __ilast && __ofirst != __olast; + ++__ofirst, (void)++__ifirst) + ::new (__detail::__voidify(*__ofirst)) + _OutType(ranges::iter_move(__ifirst)); + __guard.release(); + return {__ifirst, __ofirst}; + } + } - template - requires constructible_from, - range_rvalue_reference_t<_IRange>> - uninitialized_move_result, - safe_iterator_t<_ORange>> - uninitialized_move(_IRange&& __inr, _ORange&& __outr) - { - return ranges::uninitialized_move(ranges::begin(__inr), - ranges::end(__inr), - ranges::begin(__outr), - ranges::end(__outr)); - } + template + requires constructible_from, + range_rvalue_reference_t<_IRange>> + uninitialized_move_result, + safe_iterator_t<_ORange>> + operator()(_IRange&& __inr, _ORange&& __outr) const + { + return (*this)(ranges::begin(__inr), + ranges::end(__inr), + ranges::begin(__outr), + ranges::end(__outr)); + } + }; + + inline constexpr __uninitialized_move_fn uninitialized_move{}; template using uninitialized_move_n_result = uninitialized_copy_result<_Iter, _Out>; - template _Sent> - requires constructible_from, - iter_rvalue_reference_t<_Iter>> - uninitialized_move_n_result<_Iter, _Out> - uninitialized_move_n(_Iter __ifirst, iter_difference_t<_Iter> __n, - _Out __ofirst, _Sent __olast) - { - using _OutType = remove_reference_t>; - if constexpr (sized_sentinel_for<_Sent, _Out> - && is_trivial_v<_OutType> - && is_nothrow_assignable_v<_OutType, - iter_rvalue_reference_t<_Iter>>) - { - auto __d = ranges::distance(__ofirst, __olast); - return ranges::copy_n(std::make_move_iterator(__ifirst), - std::min(__n, __d), __ofirst); - } - else - { - auto __guard = __detail::_DestroyGuard(&__ofirst); - for (; __n > 0 && __ofirst != __olast; - ++__ofirst, (void)++__ifirst, (void)--__n) - ::new (__detail::__voidify(*__ofirst)) - _OutType(ranges::iter_move(__ifirst)); - __guard.release(); - return {__ifirst, __ofirst}; - } - } + struct __uninitialized_move_n_fn + { + template _Sent> + requires constructible_from, + iter_rvalue_reference_t<_Iter>> + uninitialized_move_n_result<_Iter, _Out> + operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, + _Out __ofirst, _Sent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_Sent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType, + iter_rvalue_reference_t<_Iter>>) + { + auto __d = ranges::distance(__ofirst, __olast); + return ranges::copy_n(std::make_move_iterator(__ifirst), + std::min(__n, __d), __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __n > 0 && __ofirst != __olast; + ++__ofirst, (void)++__ifirst, (void)--__n) + ::new (__detail::__voidify(*__ofirst)) + _OutType(ranges::iter_move(__ifirst)); + __guard.release(); + return {__ifirst, __ofirst}; + } + } + }; - template<__detail::__nothrow_forward_iterator _Iter, - __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp> - requires constructible_from, const _Tp&> - _Iter - uninitialized_fill(_Iter __first, _Sent __last, const _Tp& __x) - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivial_v<_ValueType> - && is_nothrow_assignable_v<_ValueType, const _Tp&>) - return ranges::fill(__first, __last, __x); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __first != __last; ++__first) - ::new (__detail::__voidify(*__first)) _ValueType(__x); - __guard.release(); - return __first; - } - } + inline constexpr __uninitialized_move_n_fn uninitialized_move_n{}; - template<__detail::__nothrow_forward_range _Range, typename _Tp> - requires constructible_from, const _Tp&> - safe_iterator_t<_Range> - uninitialized_fill(_Range&& __r, const _Tp& __x) - { - return ranges::uninitialized_fill(ranges::begin(__r), ranges::end(__r), - __x); - } + struct __uninitialized_fill_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp> + requires constructible_from, const _Tp&> + _Iter + operator()(_Iter __first, _Sent __last, const _Tp& __x) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_nothrow_assignable_v<_ValueType, const _Tp&>) + return ranges::fill(__first, __last, __x); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType(__x); + __guard.release(); + return __first; + } + } - template<__detail::__nothrow_forward_iterator _Iter, typename _Tp> - requires constructible_from, const _Tp&> - _Iter - uninitialized_fill_n(_Iter __first, iter_difference_t<_Iter> __n, - const _Tp& __x) - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivial_v<_ValueType> - && is_nothrow_assignable_v<_ValueType, const _Tp&>) - return ranges::fill_n(__first, __n, __x); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __n > 0; ++__first, (void)--__n) - ::new (__detail::__voidify(*__first)) _ValueType(__x); - __guard.release(); - return __first; - } - } + template<__detail::__nothrow_forward_range _Range, typename _Tp> + requires constructible_from, const _Tp&> + safe_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __x) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __x); + } + }; - template - requires requires { ::new (declval()) _Tp(declval<_Args>()...); } - constexpr _Tp* - construct_at(_Tp* __location, _Args&&... __args) - { - return ::new (__detail::__voidify(*__location)) - _Tp(std::forward<_Args>(__args)...); - } + inline constexpr __uninitialized_fill_fn uninitialized_fill{}; - template - constexpr void - destroy_at(_Tp* __location) noexcept - { - if constexpr (is_array_v<_Tp>) - ranges::destroy(ranges::begin(*__location), ranges::end(*__location)); - else - __location->~_Tp(); - } + struct __uninitialized_fill_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter, typename _Tp> + requires constructible_from, const _Tp&> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n, + const _Tp& __x) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_nothrow_assignable_v<_ValueType, const _Tp&>) + return ranges::fill_n(__first, __n, __x); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __n > 0; ++__first, (void)--__n) + ::new (__detail::__voidify(*__first)) _ValueType(__x); + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_fill_n_fn uninitialized_fill_n{}; + + struct __construct_at_fn + { + template + requires requires { ::new (declval()) _Tp(declval<_Args>()...); } + constexpr _Tp* + operator()(_Tp* __location, _Args&&... __args) const + { + return ::new (__detail::__voidify(*__location)) + _Tp(std::forward<_Args>(__args)...); + } + }; + + inline constexpr __construct_at_fn construct_at{}; + + struct __destroy_at_fn + { + template + constexpr void + operator()(_Tp* __location) const noexcept + { + if constexpr (is_array_v<_Tp>) + ranges::destroy(ranges::begin(*__location), ranges::end(*__location)); + else + __location->~_Tp(); + } + }; + + inline constexpr __destroy_at_fn destroy_at{}; template<__detail::__nothrow_input_iterator _Iter, __detail::__nothrow_sentinel<_Iter> _Sent> requires destructible> constexpr _Iter - destroy(_Iter __first, _Sent __last) noexcept + __destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept { if constexpr (is_trivially_destructible_v>) return ranges::next(__first, __last); @@ -466,23 +540,28 @@ namespace ranges template<__detail::__nothrow_input_range _Range> requires destructible> constexpr safe_iterator_t<_Range> - destroy(_Range&& __r) noexcept - { return ranges::destroy(ranges::begin(__r), ranges::end(__r)); } + __destroy_fn::operator()(_Range&& __r) const noexcept + { return (*this)(ranges::begin(__r), ranges::end(__r)); } - template<__detail::__nothrow_input_iterator _Iter> - requires destructible> - constexpr _Iter - destroy_n(_Iter __first, iter_difference_t<_Iter> __n) noexcept - { - if constexpr (is_trivially_destructible_v>) - return ranges::next(__first, __n); - else - { - for (; __n > 0; ++__first, (void)--__n) - ranges::destroy_at(std::__addressof(*__first)); - return __first; - } - } + struct __destroy_n_fn + { + template<__detail::__nothrow_input_iterator _Iter> + requires destructible> + constexpr _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept + { + if constexpr (is_trivially_destructible_v>) + return ranges::next(__first, __n); + else + { + for (; __n > 0; ++__first, (void)--__n) + ranges::destroy_at(std::__addressof(*__first)); + return __first; + } + } + }; + + inline constexpr __destroy_n_fn destroy_n{}; } _GLIBCXX_END_NAMESPACE_VERSION } // namespace std