VCCC  2024.05
VisualCamp Common C++ library
find_last.hpp
Go to the documentation of this file.
1 //
2 // Created by YongGyu Lee on 4/11/24.
3 //
4 
5 #ifndef VCCC_ALGORITHM_RANGES_FIND_LAST_HPP_
6 #define VCCC_ALGORITHM_RANGES_FIND_LAST_HPP_
7 
8 #include <functional>
9 #include <type_traits>
10 
16 #include "vccc/__iterator/next.hpp"
22 #include "vccc/__ranges/begin.hpp"
24 #include "vccc/__ranges/end.hpp"
29 
30 namespace vccc {
31 namespace ranges {
32 namespace detail {
33 
34 struct find_last_niebloid {
35  template<typename I, typename S, typename T, typename Proj = identity, std::enable_if_t<conjunction<
36  input_iterator<I>,
37  sentinel_for<S, I>,
38  projectable<I, Proj>,
39  indirect_binary_predicate<equal_to, projected<I, Proj>, const T*>
40  >::value, int> = 0>
41  constexpr subrange<I> operator()(I first, S last, const T& value, Proj proj = {}) const {
42  I found{};
43 
44  for (; first != last; ++first) {
45  if (vccc::invoke(proj, *first) == value)
46  found = first;
47  }
48 
49  if (found == I {})
50  return {first, first};
51 
52  return {found, ranges::next(found, last)};
53  }
54 
55  template<typename R, typename T, typename Proj = identity, std::enable_if_t<conjunction<
56  input_range<R>,
57  projectable<iterator_t<R>, Proj>,
58  indirect_binary_predicate<equal_to, projected<iterator_t<R>, Proj>, const T*>
59  >::value, int> = 0>
60  constexpr borrowed_subrange_t<R> operator()(R&& r, const T& value, Proj proj = {}) const {
61  return (*this)(ranges::begin(r), ranges::end(r), value, std::ref(proj));
62  }
63 };
64 
65 struct find_last_if_niebloid {
66  template<typename I, typename S, typename Proj = identity, typename Pred, std::enable_if_t<conjunction<
67  forward_iterator<I>,
68  sentinel_for<S, I>,
69  projectable<I, Proj>,
70  indirect_unary_predicate<Pred, projected<I, Proj>>
71  >::value, int> = 0>
72  constexpr subrange<I> operator()(I first, S last, Pred pred, Proj proj = {}) const {
73  I found{};
74  for (; first != last; ++first) {
75  if (vccc::invoke(pred, vccc::invoke(proj, *first))) {
76  found = first;
77  }
78  }
79 
80  if (found == I {})
81  return {first, first};
82 
83  return {found, ranges::next(found, last)};
84  }
85 
86  template<typename R, typename Proj = identity, typename Pred, std::enable_if_t<conjunction<
87  forward_range<R>,
88  projectable<iterator_t<R>, Proj>,
89  indirect_unary_predicate<Pred, projected<iterator_t<R>, Proj>>
90  >::value, int> = 0>
91  constexpr borrowed_subrange_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
92  return (*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
93  }
94 };
95 
96 struct find_last_if_not_niebloid {
97  template<typename I, typename S, typename Proj = identity, typename Pred, std::enable_if_t<conjunction<
98  forward_iterator<I>,
99  sentinel_for<S, I>,
100  projectable<I, Proj>,
101  indirect_unary_predicate<Pred, projected<I, Proj>>
102  >::value, int> = 0>
103  constexpr subrange<I> operator()(I first, S last, Pred pred, Proj proj = {}) const {
104  I found{};
105  for (; first != last; ++first) {
106  if (!vccc::invoke(pred, vccc::invoke(proj, *first))) {
107  found = first;
108  }
109  }
110 
111  if (found == I {})
112  return {first, first};
113 
114  return {found, ranges::next(found, last)};
115  }
116 
117  template<typename R, typename Proj = identity, typename Pred, std::enable_if_t<conjunction<
118  forward_range<R>,
119  projectable<iterator_t<R>, Proj>,
120  indirect_unary_predicate<Pred, projected<iterator_t<R>, Proj>>
121  >::value, int> = 0>
122  constexpr borrowed_subrange_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
123  return (*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
124  }
125 };
126 
127 } // namespace detail
128 
131 
132 VCCC_INLINE_OR_STATIC constexpr detail::find_last_niebloid find_last{};
133 VCCC_INLINE_OR_STATIC constexpr detail::find_last_if_niebloid find_last_if{};
134 VCCC_INLINE_OR_STATIC constexpr detail::find_last_if_not_niebloid find_last_if_not{};
135 
137 
138 } // namespace ranges
139 } // namespace vccc
140 
141 #endif // VCCC_ALGORITHM_RANGES_FIND_LAST_HPP_
constexpr VCCC_INLINE_OR_STATIC detail::find_last_if_niebloid find_last_if
Definition: find_last.hpp:133
constexpr VCCC_INLINE_OR_STATIC detail::find_last_niebloid find_last
Definition: find_last.hpp:132
constexpr VCCC_INLINE_OR_STATIC detail::find_last_if_not_niebloid find_last_if_not
Definition: find_last.hpp:134
constexpr invoke_result_t< F, Args... > invoke(F &&f, Args &&... args) noexcept(is_nothrow_invocable< F, Args... >::value)
Definition: invoke.hpp:38
constexpr VCCC_INLINE_OR_STATIC detail::next_niebloid next
Definition: next.hpp:65
constexpr VCCC_INLINE_OR_STATIC detail::begin_niebloid begin
returns an iterator to the beginning of a range
Definition: begin.hpp:116
constexpr VCCC_INLINE_OR_STATIC detail::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
#define VCCC_INLINE_OR_STATIC
Definition: inline_or_static.hpp:9
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 0 > first
Definition: key_value.hpp:34
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35