xref: /llvm-project/libcxx/include/__algorithm/ranges_find_last.h (revision 09e3a360581dc36d0820d3fb6da9bd7cfed87b5d)
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