Skip to content

Commit 7795436

Browse files
committed
Algorithms for ranges_find_last, find_last_if, and find_last_if_not
1 parent b13df77 commit 7795436

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___ALGORITHM_RANGES_FIND_LAST_IF_H
10+
#define _LIBCPP___ALGORITHM_RANGES_FIND_LAST_IF_H
11+
12+
#include <__config>
13+
#include <__functional/identity.h>
14+
#include <__functional/invoke.h>
15+
#include <__functional/ranges_operations.h>
16+
#include <__iterator/concepts.h>
17+
#include <__iterator/projected.h>
18+
#include <__ranges/access.h>
19+
#include <__ranges/concepts.h>
20+
#include <__ranges/dangling.h>
21+
#include <__utility/forward.h>
22+
#include <__utility/move.h>
23+
#include <optional>
24+
25+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26+
# pragma GCC system_header
27+
#endif
28+
29+
_LIBCPP_PUSH_MACROS
30+
#include <__undef_macros>
31+
32+
#if _LIBCPP_STD_VER >= 20
33+
34+
_LIBCPP_BEGIN_NAMESPACE_STD
35+
36+
namespace ranges {
37+
38+
namespace __find_last_if {
39+
40+
struct __fn {
41+
template <forward_iterator _Ip,
42+
sentinel_for<_Ip> _Sp,
43+
class _Proj = identity,
44+
indirect_unary_predicate<projected<_Ip, _Proj>> _Pred>
45+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Ip>
46+
operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const {
47+
std::optional<_Ip> __found;
48+
for (; __first != __last; ++__first) {
49+
if (std::invoke(__pred, std::invoke(__proj, *__first))) {
50+
__found = __first;
51+
}
52+
}
53+
if (!__found)
54+
return {__first, __first};
55+
return {*__found, std::ranges::next(*__found, __last)};
56+
}
57+
58+
template <forward_range _Rp,
59+
class _Proj = identity,
60+
indirect_unary_predicate<projected<iterator_t<_Rp>, _Proj>> _Pred>
61+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Rp>
62+
operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const {
63+
return this->operator()(ranges::begin(__r), ranges::end(__r), std::ref(__pred), std::ref(__proj));
64+
}
65+
};
66+
67+
} // namespace __find_last_if
68+
69+
inline namespace __cpo {
70+
inline constexpr auto find_last_if = __find_last_if::__fn{};
71+
} // namespace __cpo
72+
73+
} // namespace ranges
74+
75+
_LIBCPP_END_NAMESPACE_STD
76+
77+
#endif // _LIBCPP_STD_VER >= 20
78+
79+
_LIBCPP_POP_MACROS
80+
81+
#endif // _LIBCPP___ALGORITHM_RANGES_FIND_LAST_IF_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___ALGORITHM_RANGES_FIND_LAST_IF_NOT_H
10+
#define _LIBCPP___ALGORITHM_RANGES_FIND_LAST_IF_NOT_H
11+
12+
#include <__config>
13+
#include <__functional/identity.h>
14+
#include <__functional/invoke.h>
15+
#include <__functional/ranges_operations.h>
16+
#include <__iterator/concepts.h>
17+
#include <__iterator/projected.h>
18+
#include <__ranges/access.h>
19+
#include <__ranges/concepts.h>
20+
#include <__ranges/dangling.h>
21+
#include <__utility/forward.h>
22+
#include <__utility/move.h>
23+
#include <optional>
24+
25+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26+
# pragma GCC system_header
27+
#endif
28+
29+
_LIBCPP_PUSH_MACROS
30+
#include <__undef_macros>
31+
32+
#if _LIBCPP_STD_VER >= 20
33+
34+
_LIBCPP_BEGIN_NAMESPACE_STD
35+
36+
namespace ranges {
37+
38+
namespace __find_last_if_not {
39+
40+
struct __fn {
41+
template <forward_iterator _Ip,
42+
sentinel_for<_Ip> _Sp,
43+
class _Proj = identity,
44+
indirect_unary_predicate<projected<_Ip, _Proj>> _Pred>
45+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Ip>
46+
operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const {
47+
std::optional<_Ip> __found;
48+
for (; __first != __last; ++__first) {
49+
if (!std::invoke(__pred, std::invoke(__proj, *__first))) {
50+
__found = __first;
51+
}
52+
}
53+
if (!__found)
54+
return {__first, __first};
55+
return {*__found, std::ranges::next(*__found, __last)};
56+
}
57+
58+
template <forward_range _Rp,
59+
class _Proj = identity,
60+
indirect_unary_predicate<projected<iterator_t<_Rp>, _Proj>> _Pred>
61+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Rp>
62+
operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const {
63+
return this->operator()(ranges::begin(__r), ranges::end(__r), std::ref(__pred), std::ref(__proj));
64+
}
65+
};
66+
67+
} // namespace __find_last_if_not
68+
69+
inline namespace __cpo {
70+
inline constexpr auto find_last_if_not = __find_last_if_not::__fn{};
71+
} // namespace __cpo
72+
73+
} // namespace ranges
74+
75+
_LIBCPP_END_NAMESPACE_STD
76+
77+
#endif // _LIBCPP_STD_VER >= 20
78+
79+
_LIBCPP_POP_MACROS
80+
81+
#endif // _LIBCPP___ALGORITHM_RANGES_FIND_LAST_IF_NOT_H

0 commit comments

Comments
 (0)