104760bfaSnicole mazzuca //===----------------------------------------------------------------------===// 204760bfaSnicole mazzuca // 304760bfaSnicole mazzuca // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 404760bfaSnicole mazzuca // See https://llvm.org/LICENSE.txt for license information. 504760bfaSnicole mazzuca // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 604760bfaSnicole mazzuca // 704760bfaSnicole mazzuca //===----------------------------------------------------------------------===// 804760bfaSnicole mazzuca 904760bfaSnicole mazzuca #ifndef _LIBCPP___ALGORITHM_RANGES_FIND_LAST_H 1004760bfaSnicole mazzuca #define _LIBCPP___ALGORITHM_RANGES_FIND_LAST_H 1104760bfaSnicole mazzuca 1204760bfaSnicole mazzuca #include <__config> 1304760bfaSnicole mazzuca #include <__functional/identity.h> 1404760bfaSnicole mazzuca #include <__functional/invoke.h> 1504760bfaSnicole mazzuca #include <__functional/ranges_operations.h> 1604760bfaSnicole mazzuca #include <__iterator/concepts.h> 1704760bfaSnicole mazzuca #include <__iterator/indirectly_comparable.h> 1804760bfaSnicole mazzuca #include <__iterator/next.h> 1904760bfaSnicole mazzuca #include <__iterator/prev.h> 2004760bfaSnicole mazzuca #include <__iterator/projected.h> 2104760bfaSnicole mazzuca #include <__ranges/access.h> 2204760bfaSnicole mazzuca #include <__ranges/concepts.h> 2304760bfaSnicole mazzuca #include <__ranges/subrange.h> 24*09e3a360SLouis Dionne #include <__utility/forward.h> 2504760bfaSnicole mazzuca #include <__utility/move.h> 2604760bfaSnicole mazzuca 2704760bfaSnicole mazzuca #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2804760bfaSnicole mazzuca # pragma GCC system_header 2904760bfaSnicole mazzuca #endif 3004760bfaSnicole mazzuca 3104760bfaSnicole mazzuca _LIBCPP_PUSH_MACROS 3204760bfaSnicole mazzuca #include <__undef_macros> 3304760bfaSnicole mazzuca 3404760bfaSnicole mazzuca #if _LIBCPP_STD_VER >= 23 3504760bfaSnicole mazzuca 3604760bfaSnicole mazzuca _LIBCPP_BEGIN_NAMESPACE_STD 3704760bfaSnicole mazzuca 3804760bfaSnicole mazzuca namespace ranges { 3904760bfaSnicole mazzuca 4004760bfaSnicole mazzuca template <class _Iter, class _Sent, class _Pred, class _Proj> 4104760bfaSnicole mazzuca _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> 4204760bfaSnicole mazzuca __find_last_impl(_Iter __first, _Sent __last, _Pred __pred, _Proj& __proj) { 4304760bfaSnicole mazzuca if (__first == __last) { 4404760bfaSnicole mazzuca return subrange<_Iter>(__first, __first); 4504760bfaSnicole mazzuca } 4604760bfaSnicole mazzuca 4704760bfaSnicole mazzuca if constexpr (bidirectional_iterator<_Iter>) { 4804760bfaSnicole mazzuca auto __last_it = ranges::next(__first, __last); 4904760bfaSnicole mazzuca for (auto __it = ranges::prev(__last_it); __it != __first; --__it) { 5004760bfaSnicole mazzuca if (__pred(std::invoke(__proj, *__it))) { 5104760bfaSnicole mazzuca return subrange<_Iter>(std::move(__it), std::move(__last_it)); 5204760bfaSnicole mazzuca } 5304760bfaSnicole mazzuca } 5404760bfaSnicole mazzuca if (__pred(std::invoke(__proj, *__first))) { 5504760bfaSnicole mazzuca return subrange<_Iter>(std::move(__first), std::move(__last_it)); 5604760bfaSnicole mazzuca } 5704760bfaSnicole mazzuca return subrange<_Iter>(__last_it, __last_it); 5804760bfaSnicole mazzuca } else { 5904760bfaSnicole mazzuca bool __found = false; 6004760bfaSnicole mazzuca _Iter __found_it; 6104760bfaSnicole mazzuca for (; __first != __last; ++__first) { 6204760bfaSnicole mazzuca if (__pred(std::invoke(__proj, *__first))) { 6304760bfaSnicole mazzuca __found = true; 6404760bfaSnicole mazzuca __found_it = __first; 6504760bfaSnicole mazzuca } 6604760bfaSnicole mazzuca } 6704760bfaSnicole mazzuca 6804760bfaSnicole mazzuca if (__found) { 6904760bfaSnicole mazzuca return subrange<_Iter>(std::move(__found_it), std::move(__first)); 7004760bfaSnicole mazzuca } else { 7104760bfaSnicole mazzuca return subrange<_Iter>(__first, __first); 7204760bfaSnicole mazzuca } 7304760bfaSnicole mazzuca } 7404760bfaSnicole mazzuca } 7504760bfaSnicole mazzuca 76d10dc5a0SChristopher Di Bella struct __find_last { 7704760bfaSnicole mazzuca template <class _Type> 7804760bfaSnicole mazzuca struct __op { 7904760bfaSnicole mazzuca const _Type& __value; 8004760bfaSnicole mazzuca template <class _Elem> 8104760bfaSnicole mazzuca _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Elem&& __elem) const { 8204760bfaSnicole mazzuca return std::forward<_Elem>(__elem) == __value; 8304760bfaSnicole mazzuca } 8404760bfaSnicole mazzuca }; 8504760bfaSnicole mazzuca 8604760bfaSnicole mazzuca template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity> 8704760bfaSnicole mazzuca requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Type*> 8804760bfaSnicole mazzuca [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr static subrange<_Iter> 8904760bfaSnicole mazzuca operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) { 9004760bfaSnicole mazzuca return ranges::__find_last_impl(std::move(__first), std::move(__last), __op<_Type>{__value}, __proj); 9104760bfaSnicole mazzuca } 9204760bfaSnicole mazzuca 9304760bfaSnicole mazzuca template <forward_range _Range, class _Type, class _Proj = identity> 9404760bfaSnicole mazzuca requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*> 9504760bfaSnicole mazzuca [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr static borrowed_subrange_t<_Range> 9604760bfaSnicole mazzuca operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) { 9704760bfaSnicole mazzuca return ranges::__find_last_impl(ranges::begin(__range), ranges::end(__range), __op<_Type>{__value}, __proj); 9804760bfaSnicole mazzuca } 9904760bfaSnicole mazzuca }; 10004760bfaSnicole mazzuca 101d10dc5a0SChristopher Di Bella struct __find_last_if { 10204760bfaSnicole mazzuca template <class _Pred> 10304760bfaSnicole mazzuca struct __op { 10404760bfaSnicole mazzuca _Pred& __pred; 10504760bfaSnicole mazzuca template <class _Elem> 10604760bfaSnicole mazzuca _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Elem&& __elem) const { 10704760bfaSnicole mazzuca return std::invoke(__pred, std::forward<_Elem>(__elem)); 10804760bfaSnicole mazzuca } 10904760bfaSnicole mazzuca }; 11004760bfaSnicole mazzuca 11104760bfaSnicole mazzuca template <forward_iterator _Iter, 11204760bfaSnicole mazzuca sentinel_for<_Iter> _Sent, 11304760bfaSnicole mazzuca class _Proj = identity, 11404760bfaSnicole mazzuca indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> 11504760bfaSnicole mazzuca [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr static subrange<_Iter> 11604760bfaSnicole mazzuca operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) { 11704760bfaSnicole mazzuca return ranges::__find_last_impl(std::move(__first), std::move(__last), __op<_Pred>{__pred}, __proj); 11804760bfaSnicole mazzuca } 11904760bfaSnicole mazzuca 12004760bfaSnicole mazzuca template <forward_range _Range, 12104760bfaSnicole mazzuca class _Proj = identity, 12204760bfaSnicole mazzuca indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> 12304760bfaSnicole mazzuca [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr static borrowed_subrange_t<_Range> 12404760bfaSnicole mazzuca operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) { 12504760bfaSnicole mazzuca return ranges::__find_last_impl(ranges::begin(__range), ranges::end(__range), __op<_Pred>{__pred}, __proj); 12604760bfaSnicole mazzuca } 12704760bfaSnicole mazzuca }; 12804760bfaSnicole mazzuca 129d10dc5a0SChristopher Di Bella struct __find_last_if_not { 13004760bfaSnicole mazzuca template <class _Pred> 13104760bfaSnicole mazzuca struct __op { 13204760bfaSnicole mazzuca _Pred& __pred; 13304760bfaSnicole mazzuca template <class _Elem> 13404760bfaSnicole mazzuca _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Elem&& __elem) const { 13504760bfaSnicole mazzuca return !std::invoke(__pred, std::forward<_Elem>(__elem)); 13604760bfaSnicole mazzuca } 13704760bfaSnicole mazzuca }; 13804760bfaSnicole mazzuca 13904760bfaSnicole mazzuca template <forward_iterator _Iter, 14004760bfaSnicole mazzuca sentinel_for<_Iter> _Sent, 14104760bfaSnicole mazzuca class _Proj = identity, 14204760bfaSnicole mazzuca indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> 14304760bfaSnicole mazzuca [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr static subrange<_Iter> 14404760bfaSnicole mazzuca operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) { 14504760bfaSnicole mazzuca return ranges::__find_last_impl(std::move(__first), std::move(__last), __op<_Pred>{__pred}, __proj); 14604760bfaSnicole mazzuca } 14704760bfaSnicole mazzuca 14804760bfaSnicole mazzuca template <forward_range _Range, 14904760bfaSnicole mazzuca class _Proj = identity, 15004760bfaSnicole mazzuca indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> 15104760bfaSnicole mazzuca [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr static borrowed_subrange_t<_Range> 15204760bfaSnicole mazzuca operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) { 15304760bfaSnicole mazzuca return ranges::__find_last_impl(ranges::begin(__range), ranges::end(__range), __op<_Pred>{__pred}, __proj); 15404760bfaSnicole mazzuca } 15504760bfaSnicole mazzuca }; 15604760bfaSnicole mazzuca 15704760bfaSnicole mazzuca inline namespace __cpo { 158d10dc5a0SChristopher Di Bella inline constexpr auto find_last = __find_last{}; 159d10dc5a0SChristopher Di Bella inline constexpr auto find_last_if = __find_last_if{}; 160d10dc5a0SChristopher Di Bella inline constexpr auto find_last_if_not = __find_last_if_not{}; 16104760bfaSnicole mazzuca } // namespace __cpo 16204760bfaSnicole mazzuca } // namespace ranges 16304760bfaSnicole mazzuca 16404760bfaSnicole mazzuca _LIBCPP_END_NAMESPACE_STD 16504760bfaSnicole mazzuca 16604760bfaSnicole mazzuca #endif // _LIBCPP_STD_VER >= 23 16704760bfaSnicole mazzuca 16804760bfaSnicole mazzuca _LIBCPP_POP_MACROS 16904760bfaSnicole mazzuca 17004760bfaSnicole mazzuca #endif // _LIBCPP___ALGORITHM_RANGES_FIND_LAST_H 171