1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_RANGES_ALGORITHM_H_
6 #define BASE_RANGES_ALGORITHM_H_
7
8 #include <algorithm>
9 #include <functional>
10 #include <initializer_list>
11 #include <iterator>
12 #include <type_traits>
13 #include <utility>
14
15 #include "base/check.h"
16 #include "base/compiler_specific.h"
17 #include "base/memory/raw_ptr_exclusion.h"
18 #include "base/ranges/functional.h"
19 #include "base/ranges/ranges.h"
20
21 namespace base {
22
23 namespace internal {
24
25 // Returns a transformed version of the unary predicate `pred` applying `proj`
26 // to its argument before invoking `pred` on it.
27 // Ensures that the return type of `invoke(pred, ...)` is convertible to bool.
28 template <typename Pred, typename Proj>
ProjectedUnaryPredicate(Pred & pred,Proj & proj)29 constexpr auto ProjectedUnaryPredicate(Pred& pred, Proj& proj) noexcept {
30 return [&pred, &proj](auto&& arg) -> bool {
31 return std::invoke(pred,
32 std::invoke(proj, std::forward<decltype(arg)>(arg)));
33 };
34 }
35
36 // Returns a transformed version of the binary predicate `pred` applying `proj1`
37 // and `proj2` to its arguments before invoking `pred` on them.
38 //
39 // Provides an opt-in to considers all four permutations of projections and
40 // argument types. This is sometimes necessary to allow usage with legacy
41 // non-ranges std:: algorithms that don't support projections.
42 //
43 // These permutations are assigned different priorities to break ambiguities in
44 // case several permutations are possible, e.g. when Proj1 and Proj2 are the
45 // same type.
46 //
47 // Note that even when opting in to using all permutations of projections,
48 // calling code should still ensure that the canonical mapping of {Proj1, Proj2}
49 // to {LHS, RHS} compiles for all members of the range. This can be done by
50 // adding the following constraint:
51 //
52 // typename = indirect_result_t<Pred&,
53 // projected<iterator_t<Range1>, Proj1>,
54 // projected<iterator_t<Range2>, Proj2>>
55 //
56 // Ensures that the return type of `invoke(pred, ...)` is convertible to bool.
57 template <typename Pred, typename Proj1, typename Proj2, bool kPermute = false>
58 class BinaryPredicateProjector {
59 public:
BinaryPredicateProjector(Pred & pred,Proj1 & proj1,Proj2 & proj2)60 constexpr BinaryPredicateProjector(Pred& pred, Proj1& proj1, Proj2& proj2)
61 : pred_(pred), proj1_(proj1), proj2_(proj2) {}
62
63 private:
64 template <typename ProjT, typename ProjU, typename T, typename U>
65 using InvokeResult = std::invoke_result_t<Pred&,
66 std::invoke_result_t<ProjT&, T&&>,
67 std::invoke_result_t<ProjU&, U&&>>;
68
69 template <typename T, typename U, typename = InvokeResult<Proj1, Proj2, T, U>>
GetProjs(priority_tag<3>)70 constexpr std::pair<Proj1&, Proj2&> GetProjs(priority_tag<3>) const {
71 return {proj1_, proj2_};
72 }
73
74 template <typename T,
75 typename U,
76 bool LazyPermute = kPermute,
77 typename = std::enable_if_t<LazyPermute>,
78 typename = InvokeResult<Proj2, Proj1, T, U>>
GetProjs(priority_tag<2>)79 constexpr std::pair<Proj2&, Proj1&> GetProjs(priority_tag<2>) const {
80 return {proj2_, proj1_};
81 }
82
83 template <typename T,
84 typename U,
85 bool LazyPermute = kPermute,
86 typename = std::enable_if_t<LazyPermute>,
87 typename = InvokeResult<Proj1, Proj1, T, U>>
GetProjs(priority_tag<1>)88 constexpr std::pair<Proj1&, Proj1&> GetProjs(priority_tag<1>) const {
89 return {proj1_, proj1_};
90 }
91
92 template <typename T,
93 typename U,
94 bool LazyPermute = kPermute,
95 typename = std::enable_if_t<LazyPermute>,
96 typename = InvokeResult<Proj2, Proj2, T, U>>
GetProjs(priority_tag<0>)97 constexpr std::pair<Proj2&, Proj2&> GetProjs(priority_tag<0>) const {
98 return {proj2_, proj2_};
99 }
100
101 public:
102 template <typename T, typename U>
operator()103 constexpr bool operator()(T&& lhs, U&& rhs) const {
104 auto projs = GetProjs<T, U>(priority_tag<3>());
105 return std::invoke(pred_, std::invoke(projs.first, std::forward<T>(lhs)),
106 std::invoke(projs.second, std::forward<U>(rhs)));
107 }
108
109 private:
110 // This field is not a raw_ref<> because it was filtered by the rewriter for:
111 // #constexpr-ctor-field-initializer
112 RAW_PTR_EXCLUSION Pred& pred_;
113 // This field is not a raw_ref<> because it was filtered by the rewriter for:
114 // #constexpr-ctor-field-initializer
115 RAW_PTR_EXCLUSION Proj1& proj1_;
116 // This field is not a raw_ref<> because it was filtered by the rewriter for:
117 // #constexpr-ctor-field-initializer
118 RAW_PTR_EXCLUSION Proj2& proj2_;
119 };
120
121 // Small wrappers around BinaryPredicateProjector to make the calling side more
122 // readable.
123 template <typename Pred, typename Proj1, typename Proj2>
ProjectedBinaryPredicate(Pred & pred,Proj1 & proj1,Proj2 & proj2)124 constexpr auto ProjectedBinaryPredicate(Pred& pred,
125 Proj1& proj1,
126 Proj2& proj2) noexcept {
127 return BinaryPredicateProjector<Pred, Proj1, Proj2>(pred, proj1, proj2);
128 }
129
130 template <typename Pred, typename Proj1, typename Proj2>
PermutedProjectedBinaryPredicate(Pred & pred,Proj1 & proj1,Proj2 & proj2)131 constexpr auto PermutedProjectedBinaryPredicate(Pred& pred,
132 Proj1& proj1,
133 Proj2& proj2) noexcept {
134 return BinaryPredicateProjector<Pred, Proj1, Proj2, true>(pred, proj1, proj2);
135 }
136
137 // This alias is used below to restrict iterator based APIs to types for which
138 // `iterator_category` and the pre-increment and post-increment operators are
139 // defined. This is required in situations where otherwise an undesired overload
140 // would be chosen, e.g. copy_if. In spirit this is similar to C++20's
141 // std::input_or_output_iterator, a concept that each iterator should satisfy.
142 template <typename Iter,
143 typename = decltype(++std::declval<Iter&>()),
144 typename = decltype(std::declval<Iter&>()++)>
145 using iterator_category_t =
146 typename std::iterator_traits<Iter>::iterator_category;
147
148 // This alias is used below to restrict range based APIs to types for which
149 // `iterator_category_t` is defined for the underlying iterator. This is
150 // required in situations where otherwise an undesired overload would be chosen,
151 // e.g. transform. In spirit this is similar to C++20's std::ranges::range, a
152 // concept that each range should satisfy.
153 template <typename Range>
154 using range_category_t = iterator_category_t<ranges::iterator_t<Range>>;
155
156 } // namespace internal
157
158 namespace ranges {
159
160 // C++14 implementation of std::ranges::in_fun_result.
161 //
162 // Reference: https://wg21.link/algorithms.results#:~:text=in_fun_result
163 template <typename I, typename F>
164 struct in_fun_result {
165 NO_UNIQUE_ADDRESS I in;
166 NO_UNIQUE_ADDRESS F fun;
167
168 template <typename I2,
169 typename F2,
170 std::enable_if_t<std::is_convertible<const I&, I2>{} &&
171 std::is_convertible<const F&, F2>{}>>
in_fun_resultin_fun_result172 constexpr operator in_fun_result<I2, F2>() const& {
173 return {in, fun};
174 }
175
176 template <typename I2,
177 typename F2,
178 std::enable_if_t<std::is_convertible<I, I2>{} &&
179 std::is_convertible<F, F2>{}>>
in_fun_resultin_fun_result180 constexpr operator in_fun_result<I2, F2>() && {
181 return {std::move(in), std::move(fun)};
182 }
183 };
184
185 // TODO(crbug.com/1071094): Implement the other result types.
186
187 // [alg.nonmodifying] Non-modifying sequence operations
188 // Reference: https://wg21.link/alg.nonmodifying
189
190 // [alg.all.of] All of
191 // Reference: https://wg21.link/alg.all.of
192
193 // Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
194 //
195 // Returns: `false` if `E(i)` is `false` for some iterator `i` in the range
196 // `[first, last)`, and `true` otherwise.
197 //
198 // Complexity: At most `last - first` applications of the predicate and any
199 // projection.
200 //
201 // Reference: https://wg21.link/alg.all.of#:~:text=ranges::all_of(I
202 template <typename InputIterator,
203 typename Pred,
204 typename Proj = std::identity,
205 typename = internal::iterator_category_t<InputIterator>>
206 constexpr bool all_of(InputIterator first,
207 InputIterator last,
208 Pred pred,
209 Proj proj = {}) {
210 for (; first != last; ++first) {
211 if (!std::invoke(pred, std::invoke(proj, *first))) {
212 return false;
213 }
214 }
215
216 return true;
217 }
218
219 // Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
220 //
221 // Returns: `false` if `E(i)` is `false` for some iterator `i` in `range`, and
222 // `true` otherwise.
223 //
224 // Complexity: At most `size(range)` applications of the predicate and any
225 // projection.
226 //
227 // Reference: https://wg21.link/alg.all.of#:~:text=ranges::all_of(R
228 template <typename Range,
229 typename Pred,
230 typename Proj = std::identity,
231 typename = internal::range_category_t<Range>>
232 constexpr bool all_of(Range&& range, Pred pred, Proj proj = {}) {
233 return ranges::all_of(ranges::begin(range), ranges::end(range),
234 std::move(pred), std::move(proj));
235 }
236
237 // [alg.any.of] Any of
238 // Reference: https://wg21.link/alg.any.of
239
240 // Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
241 //
242 // Returns: `true` if `E(i)` is `true` for some iterator `i` in the range
243 // `[first, last)`, and `false` otherwise.
244 //
245 // Complexity: At most `last - first` applications of the predicate and any
246 // projection.
247 //
248 // Reference: https://wg21.link/alg.any.of#:~:text=ranges::any_of(I
249 template <typename InputIterator,
250 typename Pred,
251 typename Proj = std::identity,
252 typename = internal::iterator_category_t<InputIterator>>
253 constexpr bool any_of(InputIterator first,
254 InputIterator last,
255 Pred pred,
256 Proj proj = {}) {
257 for (; first != last; ++first) {
258 if (std::invoke(pred, std::invoke(proj, *first))) {
259 return true;
260 }
261 }
262
263 return false;
264 }
265
266 // Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
267 //
268 // Returns: `true` if `E(i)` is `true` for some iterator `i` in `range`, and
269 // `false` otherwise.
270 //
271 // Complexity: At most `size(range)` applications of the predicate and any
272 // projection.
273 //
274 // Reference: https://wg21.link/alg.any.of#:~:text=ranges::any_of(R
275 template <typename Range,
276 typename Pred,
277 typename Proj = std::identity,
278 typename = internal::range_category_t<Range>>
279 constexpr bool any_of(Range&& range, Pred pred, Proj proj = {}) {
280 return ranges::any_of(ranges::begin(range), ranges::end(range),
281 std::move(pred), std::move(proj));
282 }
283
284 // [alg.none.of] None of
285 // Reference: https://wg21.link/alg.none.of
286
287 // Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
288 //
289 // Returns: `false` if `E(i)` is `true` for some iterator `i` in the range
290 // `[first, last)`, and `true` otherwise.
291 //
292 // Complexity: At most `last - first` applications of the predicate and any
293 // projection.
294 //
295 // Reference: https://wg21.link/alg.none.of#:~:text=ranges::none_of(I
296 template <typename InputIterator,
297 typename Pred,
298 typename Proj = std::identity,
299 typename = internal::iterator_category_t<InputIterator>>
300 constexpr bool none_of(InputIterator first,
301 InputIterator last,
302 Pred pred,
303 Proj proj = {}) {
304 for (; first != last; ++first) {
305 if (std::invoke(pred, std::invoke(proj, *first))) {
306 return false;
307 }
308 }
309
310 return true;
311 }
312
313 // Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
314 //
315 // Returns: `false` if `E(i)` is `true` for some iterator `i` in `range`, and
316 // `true` otherwise.
317 //
318 // Complexity: At most `size(range)` applications of the predicate and any
319 // projection.
320 //
321 // Reference: https://wg21.link/alg.none.of#:~:text=ranges::none_of(R
322 template <typename Range,
323 typename Pred,
324 typename Proj = std::identity,
325 typename = internal::range_category_t<Range>>
326 constexpr bool none_of(Range&& range, Pred pred, Proj proj = {}) {
327 return ranges::none_of(ranges::begin(range), ranges::end(range),
328 std::move(pred), std::move(proj));
329 }
330
331 // [alg.foreach] For each
332 // Reference: https://wg21.link/alg.foreach
333
334 // Reference: https://wg21.link/algorithm.syn#:~:text=for_each_result
335 template <typename I, typename F>
336 using for_each_result = in_fun_result<I, F>;
337
338 // Effects: Calls `invoke(f, invoke(proj, *i))` for every iterator `i` in the
339 // range `[first, last)`, starting from `first` and proceeding to `last - 1`.
340 //
341 // Returns: `{last, std::move(f)}`.
342 //
343 // Complexity: Applies `f` and `proj` exactly `last - first` times.
344 //
345 // Remarks: If `f` returns a result, the result is ignored.
346 //
347 // Reference: https://wg21.link/alg.foreach#:~:text=ranges::for_each(I
348 template <typename InputIterator,
349 typename Fun,
350 typename Proj = std::identity,
351 typename = internal::iterator_category_t<InputIterator>>
352 constexpr auto for_each(InputIterator first,
353 InputIterator last,
354 Fun f,
355 Proj proj = {}) {
356 for (; first != last; ++first)
357 std::invoke(f, std::invoke(proj, *first));
358 return for_each_result<InputIterator, Fun>{first, std::move(f)};
359 }
360
361 // Effects: Calls `invoke(f, invoke(proj, *i))` for every iterator `i` in the
362 // range `range`, starting from `begin(range)` and proceeding to `end(range) -
363 // 1`.
364 //
365 // Returns: `{last, std::move(f)}`.
366 //
367 // Complexity: Applies `f` and `proj` exactly `size(range)` times.
368 //
369 // Remarks: If `f` returns a result, the result is ignored.
370 //
371 // Reference: https://wg21.link/alg.foreach#:~:text=ranges::for_each(R
372 template <typename Range,
373 typename Fun,
374 typename Proj = std::identity,
375 typename = internal::range_category_t<Range>>
376 constexpr auto for_each(Range&& range, Fun f, Proj proj = {}) {
377 return ranges::for_each(ranges::begin(range), ranges::end(range),
378 std::move(f), std::move(proj));
379 }
380
381 // Reference: https://wg21.link/algorithm.syn#:~:text=for_each_n_result
382 template <typename I, typename F>
383 using for_each_n_result = in_fun_result<I, F>;
384
385 // Preconditions: `n >= 0` is `true`.
386 //
387 // Effects: Calls `invoke(f, invoke(proj, *i))` for every iterator `i` in the
388 // range `[first, first + n)` in order.
389 //
390 // Returns: `{first + n, std::move(f)}`.
391 //
392 // Remarks: If `f` returns a result, the result is ignored.
393 //
394 // Reference: https://wg21.link/alg.foreach#:~:text=ranges::for_each_n
395 template <typename InputIterator,
396 typename Size,
397 typename Fun,
398 typename Proj = std::identity,
399 typename = internal::iterator_category_t<InputIterator>>
400 constexpr auto for_each_n(InputIterator first, Size n, Fun f, Proj proj = {}) {
401 while (n > 0) {
402 std::invoke(f, std::invoke(proj, *first));
403 ++first;
404 --n;
405 }
406
407 return for_each_n_result<InputIterator, Fun>{first, std::move(f)};
408 }
409
410 // [alg.find] Find
411 // Reference: https://wg21.link/alg.find
412
413 // Let `E(i)` be `bool(invoke(proj, *i) == value)`.
414 //
415 // Returns: The first iterator `i` in the range `[first, last)` for which `E(i)`
416 // is `true`. Returns `last` if no such iterator is found.
417 //
418 // Complexity: At most `last - first` applications of the corresponding
419 // predicate and any projection.
420 //
421 // Reference: https://wg21.link/alg.find#:~:text=ranges::find(I
422 template <typename InputIterator,
423 typename T,
424 typename Proj = std::identity,
425 typename = internal::iterator_category_t<InputIterator>>
426 constexpr auto find(InputIterator first,
427 InputIterator last,
428 const T& value,
429 Proj proj = {}) {
430 for (; first != last; ++first) {
431 if (std::invoke(proj, *first) == value) {
432 break;
433 }
434 }
435
436 return first;
437 }
438
439 // Let `E(i)` be `bool(invoke(proj, *i) == value)`.
440 //
441 // Returns: The first iterator `i` in `range` for which `E(i)` is `true`.
442 // Returns `end(range)` if no such iterator is found.
443 //
444 // Complexity: At most `size(range)` applications of the corresponding predicate
445 // and any projection.
446 //
447 // Reference: https://wg21.link/alg.find#:~:text=ranges::find(R
448 template <typename Range,
449 typename T,
450 typename Proj = std::identity,
451 typename = internal::range_category_t<Range>>
452 constexpr auto find(Range&& range, const T& value, Proj proj = {}) {
453 return ranges::find(ranges::begin(range), ranges::end(range), value,
454 std::move(proj));
455 }
456
457 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
458 //
459 // Returns: The first iterator `i` in the range `[first, last)` for which `E(i)`
460 // is `true`. Returns `last` if no such iterator is found.
461 //
462 // Complexity: At most `last - first` applications of the corresponding
463 // predicate and any projection.
464 //
465 // Reference: https://wg21.link/alg.find#:~:text=ranges::find_if(I
466 template <typename InputIterator,
467 typename Pred,
468 typename Proj = std::identity,
469 typename = internal::iterator_category_t<InputIterator>>
470 constexpr auto find_if(InputIterator first,
471 InputIterator last,
472 Pred pred,
473 Proj proj = {}) {
474 return std::find_if(first, last,
475 internal::ProjectedUnaryPredicate(pred, proj));
476 }
477
478 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
479 //
480 // Returns: The first iterator `i` in `range` for which `E(i)` is `true`.
481 // Returns `end(range)` if no such iterator is found.
482 //
483 // Complexity: At most `size(range)` applications of the corresponding predicate
484 // and any projection.
485 //
486 // Reference: https://wg21.link/alg.find#:~:text=ranges::find_if(R
487 template <typename Range,
488 typename Pred,
489 typename Proj = std::identity,
490 typename = internal::range_category_t<Range>>
491 constexpr auto find_if(Range&& range, Pred pred, Proj proj = {}) {
492 return ranges::find_if(ranges::begin(range), ranges::end(range),
493 std::move(pred), std::move(proj));
494 }
495
496 // Let `E(i)` be `bool(!invoke(pred, invoke(proj, *i)))`.
497 //
498 // Returns: The first iterator `i` in the range `[first, last)` for which `E(i)`
499 // is `true`. Returns `last` if no such iterator is found.
500 //
501 // Complexity: At most `last - first` applications of the corresponding
502 // predicate and any projection.
503 //
504 // Reference: https://wg21.link/alg.find#:~:text=ranges::find_if_not(I
505 template <typename InputIterator,
506 typename Pred,
507 typename Proj = std::identity,
508 typename = internal::iterator_category_t<InputIterator>>
509 constexpr auto find_if_not(InputIterator first,
510 InputIterator last,
511 Pred pred,
512 Proj proj = {}) {
513 return std::find_if_not(first, last,
514 internal::ProjectedUnaryPredicate(pred, proj));
515 }
516
517 // Let `E(i)` be `bool(!invoke(pred, invoke(proj, *i)))`.
518 //
519 // Returns: The first iterator `i` in `range` for which `E(i)` is `true`.
520 // Returns `end(range)` if no such iterator is found.
521 //
522 // Complexity: At most `size(range)` applications of the corresponding predicate
523 // and any projection.
524 //
525 // Reference: https://wg21.link/alg.find#:~:text=ranges::find_if_not(R
526 template <typename Range,
527 typename Pred,
528 typename Proj = std::identity,
529 typename = internal::range_category_t<Range>>
530 constexpr auto find_if_not(Range&& range, Pred pred, Proj proj = {}) {
531 return ranges::find_if_not(ranges::begin(range), ranges::end(range),
532 std::move(pred), std::move(proj));
533 }
534
535 // [alg.find.end] Find end
536 // Reference: https://wg21.link/alg.find.end
537
538 // Let:
539 // - `E(i,n)` be `invoke(pred, invoke(proj1, *(i + n)),
540 // invoke(proj2, *(first2 + n)))`
541 //
542 // - `i` be `last1` if `[first2, last2)` is empty, or if
543 // `(last2 - first2) > (last1 - first1)` is `true`, or if there is no iterator
544 // in the range `[first1, last1 - (last2 - first2))` such that for every
545 // non-negative integer `n < (last2 - first2)`, `E(i,n)` is `true`. Otherwise
546 // `i` is the last such iterator in `[first1, last1 - (last2 - first2))`.
547 //
548 // Returns: `i`
549 // Note: std::ranges::find_end(I1 first1,...) returns a range, rather than an
550 // iterator. For simplicitly we match std::find_end's return type instead.
551 //
552 // Complexity:
553 // At most `(last2 - first2) * (last1 - first1 - (last2 - first2) + 1)`
554 // applications of the corresponding predicate and any projections.
555 //
556 // Reference: https://wg21.link/alg.find.end#:~:text=ranges::find_end(I1
557 template <typename ForwardIterator1,
558 typename ForwardIterator2,
559 typename Pred = ranges::equal_to,
560 typename Proj1 = std::identity,
561 typename Proj2 = std::identity,
562 typename = internal::iterator_category_t<ForwardIterator1>,
563 typename = internal::iterator_category_t<ForwardIterator2>,
564 typename = indirect_result_t<Pred&,
565 projected<ForwardIterator1, Proj1>,
566 projected<ForwardIterator2, Proj2>>>
567 constexpr auto find_end(ForwardIterator1 first1,
568 ForwardIterator1 last1,
569 ForwardIterator2 first2,
570 ForwardIterator2 last2,
571 Pred pred = {},
572 Proj1 proj1 = {},
573 Proj2 proj2 = {}) {
574 return std::find_end(first1, last1, first2, last2,
575 internal::ProjectedBinaryPredicate(pred, proj1, proj2));
576 }
577
578 // Let:
579 // - `E(i,n)` be `invoke(pred, invoke(proj1, *(i + n)),
580 // invoke(proj2, *(first2 + n)))`
581 //
582 // - `i` be `end(range1)` if `range2` is empty, or if
583 // `size(range2) > size(range1)` is `true`, or if there is no iterator in the
584 // range `[begin(range1), end(range1) - size(range2))` such that for every
585 // non-negative integer `n < size(range2)`, `E(i,n)` is `true`. Otherwise `i`
586 // is the last such iterator in `[begin(range1), end(range1) - size(range2))`.
587 //
588 // Returns: `i`
589 // Note: std::ranges::find_end(R1&& r1,...) returns a range, rather than an
590 // iterator. For simplicitly we match std::find_end's return type instead.
591 //
592 // Complexity: At most `size(range2) * (size(range1) - size(range2) + 1)`
593 // applications of the corresponding predicate and any projections.
594 //
595 // Reference: https://wg21.link/alg.find.end#:~:text=ranges::find_end(R1
596 template <typename Range1,
597 typename Range2,
598 typename Pred = ranges::equal_to,
599 typename Proj1 = std::identity,
600 typename Proj2 = std::identity,
601 typename = internal::range_category_t<Range1>,
602 typename = internal::range_category_t<Range2>,
603 typename = indirect_result_t<Pred&,
604 projected<iterator_t<Range1>, Proj1>,
605 projected<iterator_t<Range2>, Proj2>>>
606 constexpr auto find_end(Range1&& range1,
607 Range2&& range2,
608 Pred pred = {},
609 Proj1 proj1 = {},
610 Proj2 proj2 = {}) {
611 return ranges::find_end(ranges::begin(range1), ranges::end(range1),
612 ranges::begin(range2), ranges::end(range2),
613 std::move(pred), std::move(proj1), std::move(proj2));
614 }
615
616 // [alg.find.first.of] Find first
617 // Reference: https://wg21.link/alg.find.first.of
618
619 // Let `E(i,j)` be `bool(invoke(pred, invoke(proj1, *i), invoke(proj2, *j)))`.
620 //
621 // Effects: Finds an element that matches one of a set of values.
622 //
623 // Returns: The first iterator `i` in the range `[first1, last1)` such that for
624 // some iterator `j` in the range `[first2, last2)` `E(i,j)` holds. Returns
625 // `last1` if `[first2, last2)` is empty or if no such iterator is found.
626 //
627 // Complexity: At most `(last1 - first1) * (last2 - first2)` applications of the
628 // corresponding predicate and any projections.
629 //
630 // Reference:
631 // https://wg21.link/alg.find.first.of#:~:text=ranges::find_first_of(I1
632 template <typename ForwardIterator1,
633 typename ForwardIterator2,
634 typename Pred = ranges::equal_to,
635 typename Proj1 = std::identity,
636 typename Proj2 = std::identity,
637 typename = internal::iterator_category_t<ForwardIterator1>,
638 typename = internal::iterator_category_t<ForwardIterator2>,
639 typename = indirect_result_t<Pred&,
640 projected<ForwardIterator1, Proj1>,
641 projected<ForwardIterator2, Proj2>>>
642 constexpr auto find_first_of(ForwardIterator1 first1,
643 ForwardIterator1 last1,
644 ForwardIterator2 first2,
645 ForwardIterator2 last2,
646 Pred pred = {},
647 Proj1 proj1 = {},
648 Proj2 proj2 = {}) {
649 return std::find_first_of(
650 first1, last1, first2, last2,
651 internal::ProjectedBinaryPredicate(pred, proj1, proj2));
652 }
653
654 // Let `E(i,j)` be `bool(invoke(pred, invoke(proj1, *i), invoke(proj2, *j)))`.
655 //
656 // Effects: Finds an element that matches one of a set of values.
657 //
658 // Returns: The first iterator `i` in `range1` such that for some iterator `j`
659 // in `range2` `E(i,j)` holds. Returns `end(range1)` if `range2` is empty or if
660 // no such iterator is found.
661 //
662 // Complexity: At most `size(range1) * size(range2)` applications of the
663 // corresponding predicate and any projections.
664 //
665 // Reference:
666 // https://wg21.link/alg.find.first.of#:~:text=ranges::find_first_of(R1
667 template <typename Range1,
668 typename Range2,
669 typename Pred = ranges::equal_to,
670 typename Proj1 = std::identity,
671 typename Proj2 = std::identity,
672 typename = internal::range_category_t<Range1>,
673 typename = internal::range_category_t<Range2>,
674 typename = indirect_result_t<Pred&,
675 projected<iterator_t<Range1>, Proj1>,
676 projected<iterator_t<Range2>, Proj2>>>
677 constexpr auto find_first_of(Range1&& range1,
678 Range2&& range2,
679 Pred pred = {},
680 Proj1 proj1 = {},
681 Proj2 proj2 = {}) {
682 return ranges::find_first_of(
683 ranges::begin(range1), ranges::end(range1), ranges::begin(range2),
684 ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2));
685 }
686
687 // [alg.adjacent.find] Adjacent find
688 // Reference: https://wg21.link/alg.adjacent.find
689
690 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i), invoke(proj, *(i + 1))))`.
691 //
692 // Returns: The first iterator `i` such that both `i` and `i + 1` are in the
693 // range `[first, last)` for which `E(i)` holds. Returns `last` if no such
694 // iterator is found.
695 //
696 // Complexity: Exactly `min((i - first) + 1, (last - first) - 1)` applications
697 // of the corresponding predicate, where `i` is `adjacent_find`'s return value.
698 //
699 // Reference:
700 // https://wg21.link/alg.adjacent.find#:~:text=ranges::adjacent_find(I
701 template <typename ForwardIterator,
702 typename Pred = ranges::equal_to,
703 typename Proj = std::identity,
704 typename = internal::iterator_category_t<ForwardIterator>>
705 constexpr auto adjacent_find(ForwardIterator first,
706 ForwardIterator last,
707 Pred pred = {},
708 Proj proj = {}) {
709 // Implementation inspired by cppreference.com:
710 // https://en.cppreference.com/w/cpp/algorithm/adjacent_find
711 //
712 // A reimplementation is required, because std::adjacent_find is not constexpr
713 // prior to C++20. Once we have C++20, we should switch to standard library
714 // implementation.
715 if (first == last)
716 return last;
717
718 for (ForwardIterator next = first; ++next != last; ++first) {
719 if (std::invoke(pred, std::invoke(proj, *first),
720 std::invoke(proj, *next))) {
721 return first;
722 }
723 }
724
725 return last;
726 }
727
728 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i), invoke(proj, *(i + 1))))`.
729 //
730 // Returns: The first iterator `i` such that both `i` and `i + 1` are in the
731 // range `range` for which `E(i)` holds. Returns `end(range)` if no such
732 // iterator is found.
733 //
734 // Complexity: Exactly `min((i - begin(range)) + 1, size(range) - 1)`
735 // applications of the corresponding predicate, where `i` is `adjacent_find`'s
736 // return value.
737 //
738 // Reference:
739 // https://wg21.link/alg.adjacent.find#:~:text=ranges::adjacent_find(R
740 template <typename Range,
741 typename Pred = ranges::equal_to,
742 typename Proj = std::identity,
743 typename = internal::range_category_t<Range>>
744 constexpr auto adjacent_find(Range&& range, Pred pred = {}, Proj proj = {}) {
745 return ranges::adjacent_find(ranges::begin(range), ranges::end(range),
746 std::move(pred), std::move(proj));
747 }
748
749 // [alg.count] Count
750 // Reference: https://wg21.link/alg.count
751
752 // Let `E(i)` be `invoke(proj, *i) == value`.
753 //
754 // Effects: Returns the number of iterators `i` in the range `[first, last)` for
755 // which `E(i)` holds.
756 //
757 // Complexity: Exactly `last - first` applications of the corresponding
758 // predicate and any projection.
759 //
760 // Reference: https://wg21.link/alg.count#:~:text=ranges::count(I
761 template <typename InputIterator,
762 typename T,
763 typename Proj = std::identity,
764 typename = internal::iterator_category_t<InputIterator>>
765 constexpr auto count(InputIterator first,
766 InputIterator last,
767 const T& value,
768 Proj proj = {}) {
769 // Note: In order to be able to apply `proj` to each element in [first, last)
770 // we are dispatching to std::count_if instead of std::count.
771 return std::count_if(first, last, [&proj, &value](auto&& lhs) {
772 return std::invoke(proj, std::forward<decltype(lhs)>(lhs)) == value;
773 });
774 }
775
776 // Let `E(i)` be `invoke(proj, *i) == value`.
777 //
778 // Effects: Returns the number of iterators `i` in `range` for which `E(i)`
779 // holds.
780 //
781 // Complexity: Exactly `size(range)` applications of the corresponding predicate
782 // and any projection.
783 //
784 // Reference: https://wg21.link/alg.count#:~:text=ranges::count(R
785 template <typename Range,
786 typename T,
787 typename Proj = std::identity,
788 typename = internal::range_category_t<Range>>
789 constexpr auto count(Range&& range, const T& value, Proj proj = {}) {
790 return ranges::count(ranges::begin(range), ranges::end(range), value,
791 std::move(proj));
792 }
793
794 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
795 //
796 // Effects: Returns the number of iterators `i` in the range `[first, last)` for
797 // which `E(i)` holds.
798 //
799 // Complexity: Exactly `last - first` applications of the corresponding
800 // predicate and any projection.
801 //
802 // Reference: https://wg21.link/alg.count#:~:text=ranges::count_if(I
803 template <typename InputIterator,
804 typename Pred,
805 typename Proj = std::identity,
806 typename = internal::iterator_category_t<InputIterator>>
807 constexpr auto count_if(InputIterator first,
808 InputIterator last,
809 Pred pred,
810 Proj proj = {}) {
811 return std::count_if(first, last,
812 internal::ProjectedUnaryPredicate(pred, proj));
813 }
814
815 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
816 //
817 // Effects: Returns the number of iterators `i` in `range` for which `E(i)`
818 // holds.
819 //
820 // Complexity: Exactly `size(range)` applications of the corresponding predicate
821 // and any projection.
822 //
823 // Reference: https://wg21.link/alg.count#:~:text=ranges::count_if(R
824 template <typename Range,
825 typename Pred,
826 typename Proj = std::identity,
827 typename = internal::range_category_t<Range>>
828 constexpr auto count_if(Range&& range, Pred pred, Proj proj = {}) {
829 return ranges::count_if(ranges::begin(range), ranges::end(range),
830 std::move(pred), std::move(proj));
831 }
832
833 // [mismatch] Mismatch
834 // Reference: https://wg21.link/mismatch
835
836 // Let `E(n)` be `!invoke(pred, invoke(proj1, *(first1 + n)),
837 // invoke(proj2, *(first2 + n)))`.
838 //
839 // Let `N` be `min(last1 - first1, last2 - first2)`.
840 //
841 // Returns: `{ first1 + n, first2 + n }`, where `n` is the smallest integer in
842 // `[0, N)` such that `E(n)` holds, or `N` if no such integer exists.
843 //
844 // Complexity: At most `N` applications of the corresponding predicate and any
845 // projections.
846 //
847 // Reference: https://wg21.link/mismatch#:~:text=ranges::mismatch(I1
848 template <typename ForwardIterator1,
849 typename ForwardIterator2,
850 typename Pred = ranges::equal_to,
851 typename Proj1 = std::identity,
852 typename Proj2 = std::identity,
853 typename = internal::iterator_category_t<ForwardIterator1>,
854 typename = internal::iterator_category_t<ForwardIterator2>,
855 typename = indirect_result_t<Pred&,
856 projected<ForwardIterator1, Proj1>,
857 projected<ForwardIterator2, Proj2>>>
858 constexpr auto mismatch(ForwardIterator1 first1,
859 ForwardIterator1 last1,
860 ForwardIterator2 first2,
861 ForwardIterator2 last2,
862 Pred pred = {},
863 Proj1 proj1 = {},
864 Proj2 proj2 = {}) {
865 return std::mismatch(first1, last1, first2, last2,
866 internal::ProjectedBinaryPredicate(pred, proj1, proj2));
867 }
868
869 // Let `E(n)` be `!invoke(pred, invoke(proj1, *(begin(range1) + n)),
870 // invoke(proj2, *(begin(range2) + n)))`.
871 //
872 // Let `N` be `min(size(range1), size(range2))`.
873 //
874 // Returns: `{ begin(range1) + n, begin(range2) + n }`, where `n` is the
875 // smallest integer in `[0, N)` such that `E(n)` holds, or `N` if no such
876 // integer exists.
877 //
878 // Complexity: At most `N` applications of the corresponding predicate and any
879 // projections.
880 //
881 // Reference: https://wg21.link/mismatch#:~:text=ranges::mismatch(R1
882 template <typename Range1,
883 typename Range2,
884 typename Pred = ranges::equal_to,
885 typename Proj1 = std::identity,
886 typename Proj2 = std::identity,
887 typename = internal::range_category_t<Range1>,
888 typename = internal::range_category_t<Range2>,
889 typename = indirect_result_t<Pred&,
890 projected<iterator_t<Range1>, Proj1>,
891 projected<iterator_t<Range2>, Proj2>>>
892 constexpr auto mismatch(Range1&& range1,
893 Range2&& range2,
894 Pred pred = {},
895 Proj1 proj1 = {},
896 Proj2 proj2 = {}) {
897 return ranges::mismatch(ranges::begin(range1), ranges::end(range1),
898 ranges::begin(range2), ranges::end(range2),
899 std::move(pred), std::move(proj1), std::move(proj2));
900 }
901
902 // [alg.equal] Equal
903 // Reference: https://wg21.link/alg.equal
904
905 // Let `E(i)` be
906 // `invoke(pred, invoke(proj1, *i), invoke(proj2, *(first2 + (i - first1))))`.
907 //
908 // Returns: If `last1 - first1 != last2 - first2`, return `false.` Otherwise
909 // return `true` if `E(i)` holds for every iterator `i` in the range `[first1,
910 // last1)`. Otherwise, returns `false`.
911 //
912 // Complexity: If the types of `first1`, `last1`, `first2`, and `last2` meet the
913 // `RandomAccessIterator` requirements and `last1 - first1 != last2 - first2`,
914 // then no applications of the corresponding predicate and each projection;
915 // otherwise, at most `min(last1 - first1, last2 - first2)` applications of the
916 // corresponding predicate and any projections.
917 //
918 // Reference: https://wg21.link/alg.equal#:~:text=ranges::equal(I1
919 template <typename ForwardIterator1,
920 typename ForwardIterator2,
921 typename Pred = ranges::equal_to,
922 typename Proj1 = std::identity,
923 typename Proj2 = std::identity,
924 typename = internal::iterator_category_t<ForwardIterator1>,
925 typename = internal::iterator_category_t<ForwardIterator2>,
926 typename = indirect_result_t<Pred&,
927 projected<ForwardIterator1, Proj1>,
928 projected<ForwardIterator2, Proj2>>>
929 constexpr bool equal(ForwardIterator1 first1,
930 ForwardIterator1 last1,
931 ForwardIterator2 first2,
932 ForwardIterator2 last2,
933 Pred pred = {},
934 Proj1 proj1 = {},
935 Proj2 proj2 = {}) {
936 if (std::is_constant_evaluated()) {
937 for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
938 if (!std::invoke(pred, std::invoke(proj1, *first1),
939 std::invoke(proj2, *first2))) {
940 return false;
941 }
942 }
943
944 return first1 == last1 && first2 == last2;
945 }
946
947 return std::equal(first1, last1, first2, last2,
948 internal::ProjectedBinaryPredicate(pred, proj1, proj2));
949 }
950
951 // Let `E(i)` be
952 // `invoke(pred, invoke(proj1, *i),
953 // invoke(proj2, *(begin(range2) + (i - begin(range1)))))`.
954 //
955 // Returns: If `size(range1) != size(range2)`, return `false.` Otherwise return
956 // `true` if `E(i)` holds for every iterator `i` in `range1`. Otherwise, returns
957 // `false`.
958 //
959 // Complexity: If the types of `begin(range1)`, `end(range1)`, `begin(range2)`,
960 // and `end(range2)` meet the `RandomAccessIterator` requirements and
961 // `size(range1) != size(range2)`, then no applications of the corresponding
962 // predicate and each projection;
963 // otherwise, at most `min(size(range1), size(range2))` applications of the
964 // corresponding predicate and any projections.
965 //
966 // Reference: https://wg21.link/alg.equal#:~:text=ranges::equal(R1
967 template <typename Range1,
968 typename Range2,
969 typename Pred = ranges::equal_to,
970 typename Proj1 = std::identity,
971 typename Proj2 = std::identity,
972 typename = internal::range_category_t<Range1>,
973 typename = internal::range_category_t<Range2>,
974 typename = indirect_result_t<Pred&,
975 projected<iterator_t<Range1>, Proj1>,
976 projected<iterator_t<Range2>, Proj2>>>
977 constexpr bool equal(Range1&& range1,
978 Range2&& range2,
979 Pred pred = {},
980 Proj1 proj1 = {},
981 Proj2 proj2 = {}) {
982 return ranges::equal(ranges::begin(range1), ranges::end(range1),
983 ranges::begin(range2), ranges::end(range2),
984 std::move(pred), std::move(proj1), std::move(proj2));
985 }
986
987 // [alg.is.permutation] Is permutation
988 // Reference: https://wg21.link/alg.is.permutation
989
990 // Returns: If `last1 - first1 != last2 - first2`, return `false`. Otherwise
991 // return `true` if there exists a permutation of the elements in the range
992 // `[first2, last2)`, bounded by `[pfirst, plast)`, such that
993 // `ranges::equal(first1, last1, pfirst, plast, pred, proj, proj)` returns
994 // `true`; otherwise, returns `false`.
995 //
996 // Complexity: No applications of the corresponding predicate if
997 // ForwardIterator1 and ForwardIterator2 meet the requirements of random access
998 // iterators and `last1 - first1 != last2 - first2`. Otherwise, exactly
999 // `last1 - first1` applications of the corresponding predicate and projections
1000 // if `ranges::equal(first1, last1, first2, last2, pred, proj, proj)` would
1001 // return true;
1002 // otherwise, at worst `O(N^2)`, where `N` has the value `last1 - first1`.
1003 //
1004 // Reference:
1005 // https://wg21.link/alg.is.permutation#:~:text=ranges::is_permutation(I1
1006 template <typename ForwardIterator1,
1007 typename ForwardIterator2,
1008 typename Pred = ranges::equal_to,
1009 typename Proj1 = std::identity,
1010 typename Proj2 = std::identity,
1011 typename = internal::iterator_category_t<ForwardIterator1>,
1012 typename = internal::iterator_category_t<ForwardIterator2>,
1013 typename = indirect_result_t<Pred&,
1014 projected<ForwardIterator1, Proj1>,
1015 projected<ForwardIterator2, Proj2>>>
1016 constexpr bool is_permutation(ForwardIterator1 first1,
1017 ForwardIterator1 last1,
1018 ForwardIterator2 first2,
1019 ForwardIterator2 last2,
1020 Pred pred = {},
1021 Proj1 proj1 = {},
1022 Proj2 proj2 = {}) {
1023 // Needs to opt-in to all permutations, since std::is_permutation expects
1024 // pred(proj1(lhs), proj1(rhs)) to compile.
1025 return std::is_permutation(
1026 first1, last1, first2, last2,
1027 internal::PermutedProjectedBinaryPredicate(pred, proj1, proj2));
1028 }
1029
1030 // Returns: If `size(range1) != size(range2)`, return `false`. Otherwise return
1031 // `true` if there exists a permutation of the elements in `range2`, bounded by
1032 // `[pbegin, pend)`, such that
1033 // `ranges::equal(range1, [pbegin, pend), pred, proj, proj)` returns `true`;
1034 // otherwise, returns `false`.
1035 //
1036 // Complexity: No applications of the corresponding predicate if Range1 and
1037 // Range2 meet the requirements of random access ranges and
1038 // `size(range1) != size(range2)`. Otherwise, exactly `size(range1)`
1039 // applications of the corresponding predicate and projections if
1040 // `ranges::equal(range1, range2, pred, proj, proj)` would return true;
1041 // otherwise, at worst `O(N^2)`, where `N` has the value `size(range1)`.
1042 //
1043 // Reference:
1044 // https://wg21.link/alg.is.permutation#:~:text=ranges::is_permutation(R1
1045 template <typename Range1,
1046 typename Range2,
1047 typename Pred = ranges::equal_to,
1048 typename Proj1 = std::identity,
1049 typename Proj2 = std::identity,
1050 typename = internal::range_category_t<Range1>,
1051 typename = internal::range_category_t<Range2>,
1052 typename = indirect_result_t<Pred&,
1053 projected<iterator_t<Range1>, Proj1>,
1054 projected<iterator_t<Range2>, Proj2>>>
1055 constexpr bool is_permutation(Range1&& range1,
1056 Range2&& range2,
1057 Pred pred = {},
1058 Proj1 proj1 = {},
1059 Proj2 proj2 = {}) {
1060 return ranges::is_permutation(
1061 ranges::begin(range1), ranges::end(range1), ranges::begin(range2),
1062 ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2));
1063 }
1064
1065 // [alg.search] Search
1066 // Reference: https://wg21.link/alg.search
1067
1068 // Returns: `i`, where `i` is the first iterator in the range
1069 // `[first1, last1 - (last2 - first2))` such that for every non-negative integer
1070 // `n` less than `last2 - first2` the condition
1071 // `bool(invoke(pred, invoke(proj1, *(i + n)), invoke(proj2, *(first2 + n))))`
1072 // is `true`.
1073 // Returns `last1` if no such iterator exists.
1074 // Note: std::ranges::search(I1 first1,...) returns a range, rather than an
1075 // iterator. For simplicitly we match std::search's return type instead.
1076 //
1077 // Complexity: At most `(last1 - first1) * (last2 - first2)` applications of the
1078 // corresponding predicate and projections.
1079 //
1080 // Reference: https://wg21.link/alg.search#:~:text=ranges::search(I1
1081 template <typename ForwardIterator1,
1082 typename ForwardIterator2,
1083 typename Pred = ranges::equal_to,
1084 typename Proj1 = std::identity,
1085 typename Proj2 = std::identity,
1086 typename = internal::iterator_category_t<ForwardIterator1>,
1087 typename = internal::iterator_category_t<ForwardIterator2>,
1088 typename = indirect_result_t<Pred&,
1089 projected<ForwardIterator1, Proj1>,
1090 projected<ForwardIterator2, Proj2>>>
1091 constexpr auto search(ForwardIterator1 first1,
1092 ForwardIterator1 last1,
1093 ForwardIterator2 first2,
1094 ForwardIterator2 last2,
1095 Pred pred = {},
1096 Proj1 proj1 = {},
1097 Proj2 proj2 = {}) {
1098 return std::search(first1, last1, first2, last2,
1099 internal::ProjectedBinaryPredicate(pred, proj1, proj2));
1100 }
1101
1102 // Returns: `i`, where `i` is the first iterator in the range
1103 // `[begin(range1), end(range1) - size(range2))` such that for every
1104 // non-negative integer `n` less than `size(range2)` the condition
1105 // `bool(invoke(pred, invoke(proj1, *(i + n)),
1106 // invoke(proj2, *(begin(range2) + n))))` is `true`.
1107 // Returns `end(range1)` if no such iterator exists.
1108 // Note: std::ranges::search(R1&& r1,...) returns a range, rather than an
1109 // iterator. For simplicitly we match std::search's return type instead.
1110 //
1111 // Complexity: At most `size(range1) * size(range2)` applications of the
1112 // corresponding predicate and projections.
1113 //
1114 // Reference: https://wg21.link/alg.search#:~:text=ranges::search(R1
1115 template <typename Range1,
1116 typename Range2,
1117 typename Pred = ranges::equal_to,
1118 typename Proj1 = std::identity,
1119 typename Proj2 = std::identity,
1120 typename = internal::range_category_t<Range1>,
1121 typename = internal::range_category_t<Range2>,
1122 typename = indirect_result_t<Pred&,
1123 projected<iterator_t<Range1>, Proj1>,
1124 projected<iterator_t<Range2>, Proj2>>>
1125 constexpr auto search(Range1&& range1,
1126 Range2&& range2,
1127 Pred pred = {},
1128 Proj1 proj1 = {},
1129 Proj2 proj2 = {}) {
1130 return ranges::search(ranges::begin(range1), ranges::end(range1),
1131 ranges::begin(range2), ranges::end(range2),
1132 std::move(pred), std::move(proj1), std::move(proj2));
1133 }
1134
1135 // Mandates: The type `Size` is convertible to an integral type.
1136 //
1137 // Returns: `i` where `i` is the first iterator in the range
1138 // `[first, last - count)` such that for every non-negative integer `n` less
1139 // than `count`, the following condition holds:
1140 // `invoke(pred, invoke(proj, *(i + n)), value)`.
1141 // Returns `last` if no such iterator is found.
1142 // Note: std::ranges::search_n(I1 first1,...) returns a range, rather than an
1143 // iterator. For simplicitly we match std::search_n's return type instead.
1144 //
1145 // Complexity: At most `last - first` applications of the corresponding
1146 // predicate and projection.
1147 //
1148 // Reference: https://wg21.link/alg.search#:~:text=ranges::search_n(I
1149 template <typename ForwardIterator,
1150 typename Size,
1151 typename T,
1152 typename Pred = ranges::equal_to,
1153 typename Proj = std::identity,
1154 typename = internal::iterator_category_t<ForwardIterator>>
1155 constexpr auto search_n(ForwardIterator first,
1156 ForwardIterator last,
1157 Size count,
1158 const T& value,
1159 Pred pred = {},
1160 Proj proj = {}) {
1161 // The second arg is guaranteed to be `value`, so we'll simply apply the
1162 // std::identity projection.
1163 std::identity value_proj;
1164 return std::search_n(
1165 first, last, count, value,
1166 internal::ProjectedBinaryPredicate(pred, proj, value_proj));
1167 }
1168
1169 // Mandates: The type `Size` is convertible to an integral type.
1170 //
1171 // Returns: `i` where `i` is the first iterator in the range
1172 // `[begin(range), end(range) - count)` such that for every non-negative integer
1173 // `n` less than `count`, the following condition holds:
1174 // `invoke(pred, invoke(proj, *(i + n)), value)`.
1175 // Returns `end(arnge)` if no such iterator is found.
1176 // Note: std::ranges::search_n(R1&& r1,...) returns a range, rather than an
1177 // iterator. For simplicitly we match std::search_n's return type instead.
1178 //
1179 // Complexity: At most `size(range)` applications of the corresponding predicate
1180 // and projection.
1181 //
1182 // Reference: https://wg21.link/alg.search#:~:text=ranges::search_n(R
1183 template <typename Range,
1184 typename Size,
1185 typename T,
1186 typename Pred = ranges::equal_to,
1187 typename Proj = std::identity,
1188 typename = internal::range_category_t<Range>>
1189 constexpr auto search_n(Range&& range,
1190 Size count,
1191 const T& value,
1192 Pred pred = {},
1193 Proj proj = {}) {
1194 return ranges::search_n(ranges::begin(range), ranges::end(range), count,
1195 value, std::move(pred), std::move(proj));
1196 }
1197
1198 // [alg.modifying.operations] Mutating sequence operations
1199 // Reference: https://wg21.link/alg.modifying.operations
1200
1201 // [alg.copy] Copy
1202 // Reference: https://wg21.link/alg.copy
1203
1204 // Let N be `last - first`.
1205 //
1206 // Preconditions: `result` is not in the range `[first, last)`.
1207 //
1208 // Effects: Copies elements in the range `[first, last)` into the range
1209 // `[result, result + N)` starting from `first` and proceeding to `last`. For
1210 // each non-negative integer `n < N` , performs `*(result + n) = *(first + n)`.
1211 //
1212 // Returns: `result + N`
1213 //
1214 // Complexity: Exactly `N` assignments.
1215 //
1216 // Reference: https://wg21.link/alg.copy#:~:text=ranges::copy(I
1217 template <typename InputIterator,
1218 typename OutputIterator,
1219 typename = internal::iterator_category_t<InputIterator>,
1220 typename = internal::iterator_category_t<OutputIterator>>
copy(InputIterator first,InputIterator last,OutputIterator result)1221 constexpr auto copy(InputIterator first,
1222 InputIterator last,
1223 OutputIterator result) {
1224 return std::copy(first, last, result);
1225 }
1226
1227 // Let N be `size(range)`.
1228 //
1229 // Preconditions: `result` is not in `range`.
1230 //
1231 // Effects: Copies elements in `range` into the range `[result, result + N)`
1232 // starting from `begin(range)` and proceeding to `end(range)`. For each
1233 // non-negative integer `n < N` , performs
1234 // *(result + n) = *(begin(range) + n)`.
1235 //
1236 // Returns: `result + N`
1237 //
1238 // Complexity: Exactly `N` assignments.
1239 //
1240 // Reference: https://wg21.link/alg.copy#:~:text=ranges::copy(R
1241 template <typename Range,
1242 typename OutputIterator,
1243 typename = internal::range_category_t<Range>,
1244 typename = internal::iterator_category_t<OutputIterator>>
copy(Range && range,OutputIterator result)1245 constexpr auto copy(Range&& range, OutputIterator result) {
1246 return ranges::copy(ranges::begin(range), ranges::end(range), result);
1247 }
1248
1249 // Let `N` be `max(0, n)`.
1250 //
1251 // Mandates: The type `Size` is convertible to an integral type.
1252 //
1253 // Effects: For each non-negative integer `i < N`, performs
1254 // `*(result + i) = *(first + i)`.
1255 //
1256 // Returns: `result + N`
1257 //
1258 // Complexity: Exactly `N` assignments.
1259 //
1260 // Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_n
1261 template <typename InputIterator,
1262 typename Size,
1263 typename OutputIterator,
1264 typename = internal::iterator_category_t<InputIterator>,
1265 typename = internal::iterator_category_t<OutputIterator>>
copy_n(InputIterator first,Size n,OutputIterator result)1266 constexpr auto copy_n(InputIterator first, Size n, OutputIterator result) {
1267 return std::copy_n(first, n, result);
1268 }
1269
1270 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`, and `N` be the number
1271 // of iterators `i` in the range `[first, last)` for which the condition `E(i)`
1272 // holds.
1273 //
1274 // Preconditions: The ranges `[first, last)` and
1275 // `[result, result + (last - first))` do not overlap.
1276 //
1277 // Effects: Copies all of the elements referred to by the iterator `i` in the
1278 // range `[first, last)` for which `E(i)` is true.
1279 //
1280 // Returns: `result + N`
1281 //
1282 // Complexity: Exactly `last - first` applications of the corresponding
1283 // predicate and any projection.
1284 //
1285 // Remarks: Stable.
1286 //
1287 // Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_if(I
1288 template <typename InputIterator,
1289 typename OutputIterator,
1290 typename Pred,
1291 typename Proj = std::identity,
1292 typename = internal::iterator_category_t<InputIterator>,
1293 typename = internal::iterator_category_t<OutputIterator>>
1294 constexpr auto copy_if(InputIterator first,
1295 InputIterator last,
1296 OutputIterator result,
1297 Pred pred,
1298 Proj proj = {}) {
1299 return std::copy_if(first, last, result,
1300 internal::ProjectedUnaryPredicate(pred, proj));
1301 }
1302
1303 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`, and `N` be the number
1304 // of iterators `i` in `range` for which the condition `E(i)` holds.
1305 //
1306 // Preconditions: `range` and `[result, result + size(range))` do not overlap.
1307 //
1308 // Effects: Copies all of the elements referred to by the iterator `i` in
1309 // `range` for which `E(i)` is true.
1310 //
1311 // Returns: `result + N`
1312 //
1313 // Complexity: Exactly `size(range)` applications of the corresponding predicate
1314 // and any projection.
1315 //
1316 // Remarks: Stable.
1317 //
1318 // Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_if(R
1319 template <typename Range,
1320 typename OutputIterator,
1321 typename Pred,
1322 typename Proj = std::identity,
1323 typename = internal::range_category_t<Range>,
1324 typename = internal::iterator_category_t<OutputIterator>>
1325 constexpr auto copy_if(Range&& range,
1326 OutputIterator result,
1327 Pred pred,
1328 Proj proj = {}) {
1329 return ranges::copy_if(ranges::begin(range), ranges::end(range), result,
1330 std::move(pred), std::move(proj));
1331 }
1332
1333 // Let `N` be `last - first`.
1334 //
1335 // Preconditions: `result` is not in the range `(first, last]`.
1336 //
1337 // Effects: Copies elements in the range `[first, last)` into the range
1338 // `[result - N, result)` starting from `last - 1` and proceeding to `first`.
1339 // For each positive integer `n ≤ N`, performs `*(result - n) = *(last - n)`.
1340 //
1341 // Returns: `result - N`
1342 //
1343 // Complexity: Exactly `N` assignments.
1344 //
1345 // Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_backward(I1
1346 template <typename BidirectionalIterator1,
1347 typename BidirectionalIterator2,
1348 typename = internal::iterator_category_t<BidirectionalIterator1>,
1349 typename = internal::iterator_category_t<BidirectionalIterator2>>
copy_backward(BidirectionalIterator1 first,BidirectionalIterator1 last,BidirectionalIterator2 result)1350 constexpr auto copy_backward(BidirectionalIterator1 first,
1351 BidirectionalIterator1 last,
1352 BidirectionalIterator2 result) {
1353 return std::copy_backward(first, last, result);
1354 }
1355
1356 // Let `N` be `size(range)`.
1357 //
1358 // Preconditions: `result` is not in the range `(begin(range), end(range)]`.
1359 //
1360 // Effects: Copies elements in `range` into the range `[result - N, result)`
1361 // starting from `end(range) - 1` and proceeding to `begin(range)`. For each
1362 // positive integer `n ≤ N`, performs `*(result - n) = *(end(range) - n)`.
1363 //
1364 // Returns: `result - N`
1365 //
1366 // Complexity: Exactly `N` assignments.
1367 //
1368 // Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_backward(R
1369 template <typename Range,
1370 typename BidirectionalIterator,
1371 typename = internal::range_category_t<Range>,
1372 typename = internal::iterator_category_t<BidirectionalIterator>>
copy_backward(Range && range,BidirectionalIterator result)1373 constexpr auto copy_backward(Range&& range, BidirectionalIterator result) {
1374 return ranges::copy_backward(ranges::begin(range), ranges::end(range),
1375 result);
1376 }
1377
1378 // [alg.move] Move
1379 // Reference: https://wg21.link/alg.move
1380
1381 // Let `E(n)` be `std::move(*(first + n))`.
1382 //
1383 // Let `N` be `last - first`.
1384 //
1385 // Preconditions: `result` is not in the range `[first, last)`.
1386 //
1387 // Effects: Moves elements in the range `[first, last)` into the range `[result,
1388 // result + N)` starting from `first` and proceeding to `last`. For each
1389 // non-negative integer `n < N`, performs `*(result + n) = E(n)`.
1390 //
1391 // Returns: `result + N`
1392 //
1393 // Complexity: Exactly `N` assignments.
1394 //
1395 // Reference: https://wg21.link/alg.move#:~:text=ranges::move(I
1396 template <typename InputIterator,
1397 typename OutputIterator,
1398 typename = internal::iterator_category_t<InputIterator>,
1399 typename = internal::iterator_category_t<OutputIterator>>
move(InputIterator first,InputIterator last,OutputIterator result)1400 constexpr auto move(InputIterator first,
1401 InputIterator last,
1402 OutputIterator result) {
1403 return std::move(first, last, result);
1404 }
1405
1406 // Let `E(n)` be `std::move(*(begin(range) + n))`.
1407 //
1408 // Let `N` be `size(range)`.
1409 //
1410 // Preconditions: `result` is not in `range`.
1411 //
1412 // Effects: Moves elements in `range` into the range `[result, result + N)`
1413 // starting from `begin(range)` and proceeding to `end(range)`. For each
1414 // non-negative integer `n < N`, performs `*(result + n) = E(n)`.
1415 //
1416 // Returns: `result + N`
1417 //
1418 // Complexity: Exactly `N` assignments.
1419 //
1420 // Reference: https://wg21.link/alg.move#:~:text=ranges::move(R
1421 template <typename Range,
1422 typename OutputIterator,
1423 typename = internal::range_category_t<Range>,
1424 typename = internal::iterator_category_t<OutputIterator>>
move(Range && range,OutputIterator result)1425 constexpr auto move(Range&& range, OutputIterator result) {
1426 return ranges::move(ranges::begin(range), ranges::end(range), result);
1427 }
1428
1429 // Let `E(n)` be `std::move(*(last - n))`.
1430 //
1431 // Let `N` be `last - first`.
1432 //
1433 // Preconditions: `result` is not in the range `(first, last]`.
1434 //
1435 // Effects: Moves elements in the range `[first, last)` into the range
1436 // `[result - N, result)` starting from `last - 1` and proceeding to `first`.
1437 // For each positive integer `n ≤ N`, performs `*(result - n) = E(n)`.
1438 //
1439 // Returns: `result - N`
1440 //
1441 // Complexity: Exactly `N` assignments.
1442 //
1443 // Reference: https://wg21.link/alg.move#:~:text=ranges::move_backward(I1
1444 template <typename BidirectionalIterator1,
1445 typename BidirectionalIterator2,
1446 typename = internal::iterator_category_t<BidirectionalIterator1>,
1447 typename = internal::iterator_category_t<BidirectionalIterator2>>
move_backward(BidirectionalIterator1 first,BidirectionalIterator1 last,BidirectionalIterator2 result)1448 constexpr auto move_backward(BidirectionalIterator1 first,
1449 BidirectionalIterator1 last,
1450 BidirectionalIterator2 result) {
1451 return std::move_backward(first, last, result);
1452 }
1453
1454 // Let `E(n)` be `std::move(*(end(range) - n))`.
1455 //
1456 // Let `N` be `size(range)`.
1457 //
1458 // Preconditions: `result` is not in the range `(begin(range), end(range)]`.
1459 //
1460 // Effects: Moves elements in `range` into the range `[result - N, result)`
1461 // starting from `end(range) - 1` and proceeding to `begin(range)`. For each
1462 // positive integer `n ≤ N`, performs `*(result - n) = E(n)`.
1463 //
1464 // Returns: `result - N`
1465 //
1466 // Complexity: Exactly `N` assignments.
1467 //
1468 // Reference: https://wg21.link/alg.move#:~:text=ranges::move_backward(R
1469 template <typename Range,
1470 typename BidirectionalIterator,
1471 typename = internal::range_category_t<Range>,
1472 typename = internal::iterator_category_t<BidirectionalIterator>>
move_backward(Range && range,BidirectionalIterator result)1473 constexpr auto move_backward(Range&& range, BidirectionalIterator result) {
1474 return ranges::move_backward(ranges::begin(range), ranges::end(range),
1475 result);
1476 }
1477
1478 // [alg.swap] Swap
1479 // Reference: https://wg21.link/alg.swap
1480
1481 // Let `M` be `min(last1 - first1, last2 - first2)`.
1482 //
1483 // Preconditions: The two ranges `[first1, last1)` and `[first2, last2)` do not
1484 // overlap. `*(first1 + n)` is swappable with `*(first2 + n)`.
1485 //
1486 // Effects: For each non-negative integer `n < M` performs
1487 // `swap(*(first1 + n), *(first2 + n))`
1488 //
1489 // Returns: `first2 + M`
1490 //
1491 // Complexity: Exactly `M` swaps.
1492 //
1493 // Reference: https://wg21.link/alg.swap#:~:text=ranges::swap_ranges(I1
1494 template <typename ForwardIterator1,
1495 typename ForwardIterator2,
1496 typename = internal::iterator_category_t<ForwardIterator1>,
1497 typename = internal::iterator_category_t<ForwardIterator2>>
swap_ranges(ForwardIterator1 first1,ForwardIterator1 last1,ForwardIterator2 first2,ForwardIterator2 last2)1498 constexpr auto swap_ranges(ForwardIterator1 first1,
1499 ForwardIterator1 last1,
1500 ForwardIterator2 first2,
1501 ForwardIterator2 last2) {
1502 // std::swap_ranges does not have a `last2` overload. Thus we need to
1503 // adjust `last1` to ensure to not read past `last2`.
1504 last1 = std::next(first1, std::min(std::distance(first1, last1),
1505 std::distance(first2, last2)));
1506 return std::swap_ranges(first1, last1, first2);
1507 }
1508
1509 // Let `M` be `min(size(range1), size(range2))`.
1510 //
1511 // Preconditions: The two ranges `range1` and `range2` do not overlap.
1512 // `*(begin(range1) + n)` is swappable with `*(begin(range2) + n)`.
1513 //
1514 // Effects: For each non-negative integer `n < M` performs
1515 // `swap(*(begin(range1) + n), *(begin(range2) + n))`
1516 //
1517 // Returns: `begin(range2) + M`
1518 //
1519 // Complexity: Exactly `M` swaps.
1520 //
1521 // Reference: https://wg21.link/alg.swap#:~:text=ranges::swap_ranges(R1
1522 template <typename Range1,
1523 typename Range2,
1524 typename = internal::range_category_t<Range1>,
1525 typename = internal::range_category_t<Range2>>
swap_ranges(Range1 && range1,Range2 && range2)1526 constexpr auto swap_ranges(Range1&& range1, Range2&& range2) {
1527 return ranges::swap_ranges(ranges::begin(range1), ranges::end(range1),
1528 ranges::begin(range2), ranges::end(range2));
1529 }
1530
1531 // [alg.transform] Transform
1532 // Reference: https://wg21.link/alg.transform
1533
1534 // Let `N` be `last1 - first1`,
1535 // `E(i)` be `invoke(op, invoke(proj, *(first1 + (i - result))))`.
1536 //
1537 // Preconditions: `op` does not invalidate iterators or subranges, nor modify
1538 // elements in the ranges `[first1, first1 + N]`, and `[result, result + N]`.
1539 //
1540 // Effects: Assigns through every iterator `i` in the range
1541 // `[result, result + N)` a new corresponding value equal to `E(i)`.
1542 //
1543 // Returns: `result + N`
1544 //
1545 // Complexity: Exactly `N` applications of `op` and any projections.
1546 //
1547 // Remarks: result may be equal to `first1`.
1548 //
1549 // Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(I
1550 template <typename InputIterator,
1551 typename OutputIterator,
1552 typename UnaryOperation,
1553 typename Proj = std::identity,
1554 typename = internal::iterator_category_t<InputIterator>,
1555 typename = internal::iterator_category_t<OutputIterator>,
1556 typename = indirect_result_t<UnaryOperation&,
1557 projected<InputIterator, Proj>>>
1558 constexpr auto transform(InputIterator first1,
1559 InputIterator last1,
1560 OutputIterator result,
1561 UnaryOperation op,
1562 Proj proj = {}) {
1563 return std::transform(first1, last1, result, [&op, &proj](auto&& arg) {
1564 return std::invoke(op, std::invoke(proj, std::forward<decltype(arg)>(arg)));
1565 });
1566 }
1567
1568 // Let `N` be `size(range)`,
1569 // `E(i)` be `invoke(op, invoke(proj, *(begin(range) + (i - result))))`.
1570 //
1571 // Preconditions: `op` does not invalidate iterators or subranges, nor modify
1572 // elements in the ranges `[begin(range), end(range)]`, and
1573 // `[result, result + N]`.
1574 //
1575 // Effects: Assigns through every iterator `i` in the range
1576 // `[result, result + N)` a new corresponding value equal to `E(i)`.
1577 //
1578 // Returns: `result + N`
1579 //
1580 // Complexity: Exactly `N` applications of `op` and any projections.
1581 //
1582 // Remarks: result may be equal to `begin(range)`.
1583 //
1584 // Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(R
1585 template <typename Range,
1586 typename OutputIterator,
1587 typename UnaryOperation,
1588 typename Proj = std::identity,
1589 typename = internal::range_category_t<Range>,
1590 typename = internal::iterator_category_t<OutputIterator>,
1591 typename = indirect_result_t<UnaryOperation&,
1592 projected<iterator_t<Range>, Proj>>>
1593 constexpr auto transform(Range&& range,
1594 OutputIterator result,
1595 UnaryOperation op,
1596 Proj proj = {}) {
1597 return ranges::transform(ranges::begin(range), ranges::end(range), result,
1598 std::move(op), std::move(proj));
1599 }
1600
1601 // Let:
1602 // `N` be `min(last1 - first1, last2 - first2)`,
1603 // `E(i)` be `invoke(binary_op, invoke(proj1, *(first1 + (i - result))),
1604 // invoke(proj2, *(first2 + (i - result))))`.
1605 //
1606 // Preconditions: `binary_op` does not invalidate iterators or subranges, nor
1607 // modify elements in the ranges `[first1, first1 + N]`, `[first2, first2 + N]`,
1608 // and `[result, result + N]`.
1609 //
1610 // Effects: Assigns through every iterator `i` in the range
1611 // `[result, result + N)` a new corresponding value equal to `E(i)`.
1612 //
1613 // Returns: `result + N`
1614 //
1615 // Complexity: Exactly `N` applications of `binary_op`, and any projections.
1616 //
1617 // Remarks: `result` may be equal to `first1` or `first2`.
1618 //
1619 // Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(I1
1620 template <typename ForwardIterator1,
1621 typename ForwardIterator2,
1622 typename OutputIterator,
1623 typename BinaryOperation,
1624 typename Proj1 = std::identity,
1625 typename Proj2 = std::identity,
1626 typename = internal::iterator_category_t<ForwardIterator1>,
1627 typename = internal::iterator_category_t<ForwardIterator2>,
1628 typename = internal::iterator_category_t<OutputIterator>,
1629 typename = indirect_result_t<BinaryOperation&,
1630 projected<ForwardIterator1, Proj1>,
1631 projected<ForwardIterator2, Proj2>>>
1632 constexpr auto transform(ForwardIterator1 first1,
1633 ForwardIterator1 last1,
1634 ForwardIterator2 first2,
1635 ForwardIterator2 last2,
1636 OutputIterator result,
1637 BinaryOperation binary_op,
1638 Proj1 proj1 = {},
1639 Proj2 proj2 = {}) {
1640 // std::transform does not have a `last2` overload. Thus we need to adjust
1641 // `last1` to ensure to not read past `last2`.
1642 last1 = std::next(first1, std::min(std::distance(first1, last1),
1643 std::distance(first2, last2)));
1644 return std::transform(
1645 first1, last1, first2, result,
1646 [&binary_op, &proj1, &proj2](auto&& lhs, auto&& rhs) {
1647 return std::invoke(
1648 binary_op, std::invoke(proj1, std::forward<decltype(lhs)>(lhs)),
1649 std::invoke(proj2, std::forward<decltype(rhs)>(rhs)));
1650 });
1651 }
1652
1653 // Let:
1654 // `N` be `min(size(range1), size(range2)`,
1655 // `E(i)` be `invoke(binary_op, invoke(proj1, *(begin(range1) + (i - result))),
1656 // invoke(proj2, *(begin(range2) + (i - result))))`
1657 //
1658 // Preconditions: `binary_op` does not invalidate iterators or subranges, nor
1659 // modify elements in the ranges `[begin(range1), end(range1)]`,
1660 // `[begin(range2), end(range2)]`, and `[result, result + N]`.
1661 //
1662 // Effects: Assigns through every iterator `i` in the range
1663 // `[result, result + N)` a new corresponding value equal to `E(i)`.
1664 //
1665 // Returns: `result + N`
1666 //
1667 // Complexity: Exactly `N` applications of `binary_op`, and any projections.
1668 //
1669 // Remarks: `result` may be equal to `begin(range1)` or `begin(range2)`.
1670 //
1671 // Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(R1
1672 template <typename Range1,
1673 typename Range2,
1674 typename OutputIterator,
1675 typename BinaryOperation,
1676 typename Proj1 = std::identity,
1677 typename Proj2 = std::identity,
1678 typename = internal::range_category_t<Range1>,
1679 typename = internal::range_category_t<Range2>,
1680 typename = internal::iterator_category_t<OutputIterator>,
1681 typename = indirect_result_t<BinaryOperation&,
1682 projected<iterator_t<Range1>, Proj1>,
1683 projected<iterator_t<Range2>, Proj2>>>
1684 constexpr auto transform(Range1&& range1,
1685 Range2&& range2,
1686 OutputIterator result,
1687 BinaryOperation binary_op,
1688 Proj1 proj1 = {},
1689 Proj2 proj2 = {}) {
1690 return ranges::transform(ranges::begin(range1), ranges::end(range1),
1691 ranges::begin(range2), ranges::end(range2), result,
1692 std::move(binary_op), std::move(proj1),
1693 std::move(proj2));
1694 }
1695
1696 // [alg.replace] Replace
1697 // Reference: https://wg21.link/alg.replace
1698
1699 // Let `E(i)` be `bool(invoke(proj, *i) == old_value)`.
1700 //
1701 // Mandates: `new_value` is writable to `first`.
1702 //
1703 // Effects: Substitutes elements referred by the iterator `i` in the range
1704 // `[first, last)` with `new_value`, when `E(i)` is true.
1705 //
1706 // Returns: `last`
1707 //
1708 // Complexity: Exactly `last - first` applications of the corresponding
1709 // predicate and any projection.
1710 //
1711 // Reference: https://wg21.link/alg.replace#:~:text=ranges::replace(I
1712 template <typename ForwardIterator,
1713 typename T,
1714 typename Proj = std::identity,
1715 typename = internal::iterator_category_t<ForwardIterator>>
1716 constexpr auto replace(ForwardIterator first,
1717 ForwardIterator last,
1718 const T& old_value,
1719 const T& new_value,
1720 Proj proj = {}) {
1721 // Note: In order to be able to apply `proj` to each element in [first, last)
1722 // we are dispatching to std::replace_if instead of std::replace.
1723 std::replace_if(
1724 first, last,
1725 [&proj, &old_value](auto&& lhs) {
1726 return std::invoke(proj, std::forward<decltype(lhs)>(lhs)) == old_value;
1727 },
1728 new_value);
1729 return last;
1730 }
1731
1732 // Let `E(i)` be `bool(invoke(proj, *i) == old_value)`.
1733 //
1734 // Mandates: `new_value` is writable to `begin(range)`.
1735 //
1736 // Effects: Substitutes elements referred by the iterator `i` in `range` with
1737 // `new_value`, when `E(i)` is true.
1738 //
1739 // Returns: `end(range)`
1740 //
1741 // Complexity: Exactly `size(range)` applications of the corresponding predicate
1742 // and any projection.
1743 //
1744 // Reference: https://wg21.link/alg.replace#:~:text=ranges::replace(R
1745 template <typename Range,
1746 typename T,
1747 typename Proj = std::identity,
1748 typename = internal::range_category_t<Range>>
1749 constexpr auto replace(Range&& range,
1750 const T& old_value,
1751 const T& new_value,
1752 Proj proj = {}) {
1753 return ranges::replace(ranges::begin(range), ranges::end(range), old_value,
1754 new_value, std::move(proj));
1755 }
1756
1757 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
1758 //
1759 // Mandates: `new_value` is writable to `first`.
1760 //
1761 // Effects: Substitutes elements referred by the iterator `i` in the range
1762 // `[first, last)` with `new_value`, when `E(i)` is true.
1763 //
1764 // Returns: `last`
1765 //
1766 // Complexity: Exactly `last - first` applications of the corresponding
1767 // predicate and any projection.
1768 //
1769 // Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_if(I
1770 template <typename ForwardIterator,
1771 typename Predicate,
1772 typename T,
1773 typename Proj = std::identity,
1774 typename = internal::iterator_category_t<ForwardIterator>>
1775 constexpr auto replace_if(ForwardIterator first,
1776 ForwardIterator last,
1777 Predicate pred,
1778 const T& new_value,
1779 Proj proj = {}) {
1780 std::replace_if(first, last, internal::ProjectedUnaryPredicate(pred, proj),
1781 new_value);
1782 return last;
1783 }
1784
1785 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
1786 //
1787 // Mandates: `new_value` is writable to `begin(range)`.
1788 //
1789 // Effects: Substitutes elements referred by the iterator `i` in `range` with
1790 // `new_value`, when `E(i)` is true.
1791 //
1792 // Returns: `end(range)`
1793 //
1794 // Complexity: Exactly `size(range)` applications of the corresponding predicate
1795 // and any projection.
1796 //
1797 // Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_if(R
1798 template <typename Range,
1799 typename Predicate,
1800 typename T,
1801 typename Proj = std::identity,
1802 typename = internal::range_category_t<Range>>
1803 constexpr auto replace_if(Range&& range,
1804 Predicate pred,
1805 const T& new_value,
1806 Proj proj = {}) {
1807 return ranges::replace_if(ranges::begin(range), ranges::end(range),
1808 std::move(pred), new_value, std::move(proj));
1809 }
1810
1811 // Let `E(i)` be `bool(invoke(proj, *(first + (i - result))) == old_value)`.
1812 //
1813 // Mandates: The results of the expressions `*first` and `new_value` are
1814 // writable to `result`.
1815 //
1816 // Preconditions: The ranges `[first, last)` and `[result, result + (last -
1817 // first))` do not overlap.
1818 //
1819 // Effects: Assigns through every iterator `i` in the range `[result, result +
1820 // (last - first))` a new corresponding value, `new_value` if `E(i)` is true, or
1821 // `*(first + (i - result))` otherwise.
1822 //
1823 // Returns: `result + (last - first)`.
1824 //
1825 // Complexity: Exactly `last - first` applications of the corresponding
1826 // predicate and any projection.
1827 //
1828 // Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy(I
1829 template <typename InputIterator,
1830 typename OutputIterator,
1831 typename T,
1832 typename Proj = std::identity,
1833 typename = internal::iterator_category_t<InputIterator>,
1834 typename = internal::iterator_category_t<OutputIterator>>
1835 constexpr auto replace_copy(InputIterator first,
1836 InputIterator last,
1837 OutputIterator result,
1838 const T& old_value,
1839 const T& new_value,
1840 Proj proj = {}) {
1841 // Note: In order to be able to apply `proj` to each element in [first, last)
1842 // we are dispatching to std::replace_copy_if instead of std::replace_copy.
1843 std::replace_copy_if(
1844 first, last, result,
1845 [&proj, &old_value](auto&& lhs) {
1846 return std::invoke(proj, std::forward<decltype(lhs)>(lhs)) == old_value;
1847 },
1848 new_value);
1849 return last;
1850 }
1851
1852 // Let `E(i)` be
1853 // `bool(invoke(proj, *(begin(range) + (i - result))) == old_value)`.
1854 //
1855 // Mandates: The results of the expressions `*begin(range)` and `new_value` are
1856 // writable to `result`.
1857 //
1858 // Preconditions: The ranges `range` and `[result, result + size(range))` do not
1859 // overlap.
1860 //
1861 // Effects: Assigns through every iterator `i` in the range `[result, result +
1862 // size(range))` a new corresponding value, `new_value` if `E(i)` is true, or
1863 // `*(begin(range) + (i - result))` otherwise.
1864 //
1865 // Returns: `result + size(range)`.
1866 //
1867 // Complexity: Exactly `size(range)` applications of the corresponding
1868 // predicate and any projection.
1869 //
1870 // Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy(R
1871 template <typename Range,
1872 typename OutputIterator,
1873 typename T,
1874 typename Proj = std::identity,
1875 typename = internal::range_category_t<Range>,
1876 typename = internal::iterator_category_t<OutputIterator>>
1877 constexpr auto replace_copy(Range&& range,
1878 OutputIterator result,
1879 const T& old_value,
1880 const T& new_value,
1881 Proj proj = {}) {
1882 return ranges::replace_copy(ranges::begin(range), ranges::end(range), result,
1883 old_value, new_value, std::move(proj));
1884 }
1885
1886 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *(first + (i - result)))))`.
1887 //
1888 // Mandates: The results of the expressions `*first` and `new_value` are
1889 // writable to `result`.
1890 //
1891 // Preconditions: The ranges `[first, last)` and `[result, result + (last -
1892 // first))` do not overlap.
1893 //
1894 // Effects: Assigns through every iterator `i` in the range `[result, result +
1895 // (last - first))` a new corresponding value, `new_value` if `E(i)` is true, or
1896 // `*(first + (i - result))` otherwise.
1897 //
1898 // Returns: `result + (last - first)`.
1899 //
1900 // Complexity: Exactly `last - first` applications of the corresponding
1901 // predicate and any projection.
1902 //
1903 // Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy_if(I
1904 template <typename InputIterator,
1905 typename OutputIterator,
1906 typename Predicate,
1907 typename T,
1908 typename Proj = std::identity,
1909 typename = internal::iterator_category_t<InputIterator>,
1910 typename = internal::iterator_category_t<OutputIterator>>
1911 constexpr auto replace_copy_if(InputIterator first,
1912 InputIterator last,
1913 OutputIterator result,
1914 Predicate pred,
1915 const T& new_value,
1916 Proj proj = {}) {
1917 return std::replace_copy_if(first, last, result,
1918 internal::ProjectedUnaryPredicate(pred, proj),
1919 new_value);
1920 }
1921
1922 // Let `E(i)` be
1923 // `bool(invoke(pred, invoke(proj, *(begin(range) + (i - result)))))`.
1924 //
1925 // Mandates: The results of the expressions `*begin(range)` and `new_value` are
1926 // writable to `result`.
1927 //
1928 // Preconditions: The ranges `range` and `[result, result + size(range))` do not
1929 // overlap.
1930 //
1931 // Effects: Assigns through every iterator `i` in the range `[result, result +
1932 // size(range))` a new corresponding value, `new_value` if `E(i)` is true, or
1933 // `*(begin(range) + (i - result))` otherwise.
1934 //
1935 // Returns: `result + size(range)`.
1936 //
1937 // Complexity: Exactly `size(range)` applications of the corresponding
1938 // predicate and any projection.
1939 //
1940 // Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy_if(R
1941 template <typename Range,
1942 typename OutputIterator,
1943 typename Predicate,
1944 typename T,
1945 typename Proj = std::identity,
1946 typename = internal::range_category_t<Range>,
1947 typename = internal::iterator_category_t<OutputIterator>>
1948 constexpr auto replace_copy_if(Range&& range,
1949 OutputIterator result,
1950 Predicate pred,
1951 const T& new_value,
1952 Proj proj = {}) {
1953 return ranges::replace_copy_if(ranges::begin(range), ranges::end(range),
1954 result, pred, new_value, std::move(proj));
1955 }
1956
1957 // [alg.fill] Fill
1958 // Reference: https://wg21.link/alg.fill
1959
1960 // Let `N` be `last - first`.
1961 //
1962 // Mandates: The expression `value` is writable to the output iterator.
1963 //
1964 // Effects: Assigns `value` through all the iterators in the range
1965 // `[first, last)`.
1966 //
1967 // Returns: `last`.
1968 //
1969 // Complexity: Exactly `N` assignments.
1970 //
1971 // Reference: https://wg21.link/alg.fill#:~:text=ranges::fill(O
1972 template <typename OutputIterator,
1973 typename T,
1974 typename = internal::iterator_category_t<OutputIterator>>
fill(OutputIterator first,OutputIterator last,const T & value)1975 constexpr auto fill(OutputIterator first, OutputIterator last, const T& value) {
1976 std::fill(first, last, value);
1977 return last;
1978 }
1979
1980 // Let `N` be `size(range)`.
1981 //
1982 // Mandates: The expression `value` is writable to the output iterator.
1983 //
1984 // Effects: Assigns `value` through all the iterators in `range`.
1985 //
1986 // Returns: `end(range)`.
1987 //
1988 // Complexity: Exactly `N` assignments.
1989 //
1990 // Reference: https://wg21.link/alg.fill#:~:text=ranges::fill(R
1991 template <typename Range,
1992 typename T,
1993 typename = internal::range_category_t<Range>>
fill(Range && range,const T & value)1994 constexpr auto fill(Range&& range, const T& value) {
1995 return ranges::fill(ranges::begin(range), ranges::end(range), value);
1996 }
1997
1998 // Let `N` be `max(0, n)`.
1999 //
2000 // Mandates: The expression `value` is writable to the output iterator.
2001 // The type `Size` is convertible to an integral type.
2002 //
2003 // Effects: Assigns `value` through all the iterators in `[first, first + N)`.
2004 //
2005 // Returns: `first + N`.
2006 //
2007 // Complexity: Exactly `N` assignments.
2008 //
2009 // Reference: https://wg21.link/alg.fill#:~:text=ranges::fill_n(O
2010 template <typename OutputIterator,
2011 typename Size,
2012 typename T,
2013 typename = internal::iterator_category_t<OutputIterator>>
fill_n(OutputIterator first,Size n,const T & value)2014 constexpr auto fill_n(OutputIterator first, Size n, const T& value) {
2015 return std::fill_n(first, n, value);
2016 }
2017
2018 // [alg.generate] Generate
2019 // Reference: https://wg21.link/alg.generate
2020
2021 // Let `N` be `last - first`.
2022 //
2023 // Effects: Assigns the result of successive evaluations of gen() through each
2024 // iterator in the range `[first, last)`.
2025 //
2026 // Returns: `last`.
2027 //
2028 // Complexity: Exactly `N` evaluations of `gen()` and assignments.
2029 //
2030 // Reference: https://wg21.link/alg.generate#:~:text=ranges::generate(O
2031 template <typename OutputIterator,
2032 typename Generator,
2033 typename = internal::iterator_category_t<OutputIterator>>
generate(OutputIterator first,OutputIterator last,Generator gen)2034 constexpr auto generate(OutputIterator first,
2035 OutputIterator last,
2036 Generator gen) {
2037 std::generate(first, last, std::move(gen));
2038 return last;
2039 }
2040
2041 // Let `N` be `size(range)`.
2042 //
2043 // Effects: Assigns the result of successive evaluations of gen() through each
2044 // iterator in `range`.
2045 //
2046 // Returns: `end(range)`.
2047 //
2048 // Complexity: Exactly `N` evaluations of `gen()` and assignments.
2049 //
2050 // Reference: https://wg21.link/alg.generate#:~:text=ranges::generate(R
2051 template <typename Range,
2052 typename Generator,
2053 typename = internal::range_category_t<Range>>
generate(Range && range,Generator gen)2054 constexpr auto generate(Range&& range, Generator gen) {
2055 return ranges::generate(ranges::begin(range), ranges::end(range),
2056 std::move(gen));
2057 }
2058
2059 // Let `N` be `max(0, n)`.
2060 //
2061 // Mandates: `Size` is convertible to an integral type.
2062 //
2063 // Effects: Assigns the result of successive evaluations of gen() through each
2064 // iterator in the range `[first, first + N)`.
2065 //
2066 // Returns: `first + N`.
2067 //
2068 // Complexity: Exactly `N` evaluations of `gen()` and assignments.
2069 //
2070 // Reference: https://wg21.link/alg.generate#:~:text=ranges::generate_n(O
2071 template <typename OutputIterator,
2072 typename Size,
2073 typename Generator,
2074 typename = internal::iterator_category_t<OutputIterator>>
generate_n(OutputIterator first,Size n,Generator gen)2075 constexpr auto generate_n(OutputIterator first, Size n, Generator gen) {
2076 return std::generate_n(first, n, std::move(gen));
2077 }
2078
2079 // [alg.remove] Remove
2080 // Reference: https://wg21.link/alg.remove
2081
2082 // Let `E(i)` be `bool(invoke(proj, *i) == value)`.
2083 //
2084 // Effects: Eliminates all the elements referred to by iterator `i` in the range
2085 // `[first, last)` for which `E(i)` holds.
2086 //
2087 // Returns: The end of the resulting range.
2088 //
2089 // Remarks: Stable.
2090 //
2091 // Complexity: Exactly `last - first` applications of the corresponding
2092 // predicate and any projection.
2093 //
2094 // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove(I
2095 template <typename ForwardIterator,
2096 typename T,
2097 typename Proj = std::identity,
2098 typename = internal::iterator_category_t<ForwardIterator>>
2099 constexpr auto remove(ForwardIterator first,
2100 ForwardIterator last,
2101 const T& value,
2102 Proj proj = {}) {
2103 // Note: In order to be able to apply `proj` to each element in [first, last)
2104 // we are dispatching to std::remove_if instead of std::remove.
2105 return std::remove_if(first, last, [&proj, &value](auto&& lhs) {
2106 return std::invoke(proj, std::forward<decltype(lhs)>(lhs)) == value;
2107 });
2108 }
2109
2110 // Let `E(i)` be `bool(invoke(proj, *i) == value)`.
2111 //
2112 // Effects: Eliminates all the elements referred to by iterator `i` in `range`
2113 // for which `E(i)` holds.
2114 //
2115 // Returns: The end of the resulting range.
2116 //
2117 // Remarks: Stable.
2118 //
2119 // Complexity: Exactly `size(range)` applications of the corresponding predicate
2120 // and any projection.
2121 //
2122 // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove(R
2123 template <typename Range,
2124 typename T,
2125 typename Proj = std::identity,
2126 typename = internal::range_category_t<Range>>
2127 constexpr auto remove(Range&& range, const T& value, Proj proj = {}) {
2128 return ranges::remove(ranges::begin(range), ranges::end(range), value,
2129 std::move(proj));
2130 }
2131
2132 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
2133 //
2134 // Effects: Eliminates all the elements referred to by iterator `i` in the range
2135 // `[first, last)` for which `E(i)` holds.
2136 //
2137 // Returns: The end of the resulting range.
2138 //
2139 // Remarks: Stable.
2140 //
2141 // Complexity: Exactly `last - first` applications of the corresponding
2142 // predicate and any projection.
2143 //
2144 // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_if(I
2145 template <typename ForwardIterator,
2146 typename Predicate,
2147 typename Proj = std::identity,
2148 typename = internal::iterator_category_t<ForwardIterator>>
2149 constexpr auto remove_if(ForwardIterator first,
2150 ForwardIterator last,
2151 Predicate pred,
2152 Proj proj = {}) {
2153 return std::remove_if(first, last,
2154 internal::ProjectedUnaryPredicate(pred, proj));
2155 }
2156
2157 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
2158 //
2159 // Effects: Eliminates all the elements referred to by iterator `i` in `range`.
2160 //
2161 // Returns: The end of the resulting range.
2162 //
2163 // Remarks: Stable.
2164 //
2165 // Complexity: Exactly `size(range)` applications of the corresponding predicate
2166 // and any projection.
2167 //
2168 // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_if(R
2169 template <typename Range,
2170 typename Predicate,
2171 typename Proj = std::identity,
2172 typename = internal::range_category_t<Range>>
2173 constexpr auto remove_if(Range&& range, Predicate pred, Proj proj = {}) {
2174 return ranges::remove_if(ranges::begin(range), ranges::end(range),
2175 std::move(pred), std::move(proj));
2176 }
2177
2178 // Let `E(i)` be `bool(invoke(proj, *i) == value)`.
2179 //
2180 // Let `N` be the number of elements in `[first, last)` for which `E(i)` is
2181 // false.
2182 //
2183 // Mandates: `*first` is writable to `result`.
2184 //
2185 // Preconditions: The ranges `[first, last)` and `[result, result + (last -
2186 // first))` do not overlap.
2187 //
2188 // Effects: Copies all the elements referred to by the iterator `i` in the range
2189 // `[first, last)` for which `E(i)` is false.
2190 //
2191 // Returns: `result + N`.
2192 //
2193 // Complexity: Exactly `last - first` applications of the corresponding
2194 // predicate and any projection.
2195 //
2196 // Remarks: Stable.
2197 //
2198 // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_copy(I
2199 template <typename InputIterator,
2200 typename OutputIterator,
2201 typename T,
2202 typename Proj = std::identity,
2203 typename = internal::iterator_category_t<InputIterator>,
2204 typename = internal::iterator_category_t<OutputIterator>>
2205 constexpr auto remove_copy(InputIterator first,
2206 InputIterator last,
2207 OutputIterator result,
2208 const T& value,
2209 Proj proj = {}) {
2210 // Note: In order to be able to apply `proj` to each element in [first, last)
2211 // we are dispatching to std::remove_copy_if instead of std::remove_copy.
2212 return std::remove_copy_if(first, last, result, [&proj, &value](auto&& lhs) {
2213 return std::invoke(proj, std::forward<decltype(lhs)>(lhs)) == value;
2214 });
2215 }
2216
2217 // Let `E(i)` be `bool(invoke(proj, *i) == value)`.
2218 //
2219 // Let `N` be the number of elements in `range` for which `E(i)` is false.
2220 //
2221 // Mandates: `*begin(range)` is writable to `result`.
2222 //
2223 // Preconditions: The ranges `range` and `[result, result + size(range))` do not
2224 // overlap.
2225 //
2226 // Effects: Copies all the elements referred to by the iterator `i` in `range`
2227 // for which `E(i)` is false.
2228 //
2229 // Returns: `result + N`.
2230 //
2231 // Complexity: Exactly `size(range)` applications of the corresponding
2232 // predicate and any projection.
2233 //
2234 // Remarks: Stable.
2235 //
2236 // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_copy(R
2237 template <typename Range,
2238 typename OutputIterator,
2239 typename T,
2240 typename Proj = std::identity,
2241 typename = internal::range_category_t<Range>,
2242 typename = internal::iterator_category_t<OutputIterator>>
2243 constexpr auto remove_copy(Range&& range,
2244 OutputIterator result,
2245 const T& value,
2246 Proj proj = {}) {
2247 return ranges::remove_copy(ranges::begin(range), ranges::end(range), result,
2248 value, std::move(proj));
2249 }
2250
2251 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
2252 //
2253 // Let `N` be the number of elements in `[first, last)` for which `E(i)` is
2254 // false.
2255 //
2256 // Mandates: `*first` is writable to `result`.
2257 //
2258 // Preconditions: The ranges `[first, last)` and `[result, result + (last -
2259 // first))` do not overlap.
2260 //
2261 // Effects: Copies all the elements referred to by the iterator `i` in the range
2262 // `[first, last)` for which `E(i)` is false.
2263 //
2264 // Returns: `result + N`.
2265 //
2266 // Complexity: Exactly `last - first` applications of the corresponding
2267 // predicate and any projection.
2268 //
2269 // Remarks: Stable.
2270 //
2271 // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_copy_if(I
2272 template <typename InputIterator,
2273 typename OutputIterator,
2274 typename Pred,
2275 typename Proj = std::identity,
2276 typename = internal::iterator_category_t<InputIterator>,
2277 typename = internal::iterator_category_t<OutputIterator>>
2278 constexpr auto remove_copy_if(InputIterator first,
2279 InputIterator last,
2280 OutputIterator result,
2281 Pred pred,
2282 Proj proj = {}) {
2283 return std::remove_copy_if(first, last, result,
2284 internal::ProjectedUnaryPredicate(pred, proj));
2285 }
2286
2287 // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
2288 //
2289 // Let `N` be the number of elements in `range` for which `E(i)` is false.
2290 //
2291 // Mandates: `*begin(range)` is writable to `result`.
2292 //
2293 // Preconditions: The ranges `range` and `[result, result + size(range))` do not
2294 // overlap.
2295 //
2296 // Effects: Copies all the elements referred to by the iterator `i` in `range`
2297 // for which `E(i)` is false.
2298 //
2299 // Returns: `result + N`.
2300 //
2301 // Complexity: Exactly `size(range)` applications of the corresponding
2302 // predicate and any projection.
2303 //
2304 // Remarks: Stable.
2305 //
2306 // Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_copy(R
2307 template <typename Range,
2308 typename OutputIterator,
2309 typename Pred,
2310 typename Proj = std::identity,
2311 typename = internal::range_category_t<Range>,
2312 typename = internal::iterator_category_t<OutputIterator>>
2313 constexpr auto remove_copy_if(Range&& range,
2314 OutputIterator result,
2315 Pred pred,
2316 Proj proj = {}) {
2317 return ranges::remove_copy_if(ranges::begin(range), ranges::end(range),
2318 result, std::move(pred), std::move(proj));
2319 }
2320
2321 // [alg.unique] Unique
2322 // Reference: https://wg21.link/alg.unique
2323
2324 // Let `E(i)` be `bool(invoke(comp, invoke(proj, *(i - 1)), invoke(proj, *i)))`.
2325 //
2326 // Effects: For a nonempty range, eliminates all but the first element from
2327 // every consecutive group of equivalent elements referred to by the iterator
2328 // `i` in the range `[first + 1, last)` for which `E(i)` is true.
2329 //
2330 // Returns: The end of the resulting range.
2331 //
2332 // Complexity: For nonempty ranges, exactly `(last - first) - 1` applications of
2333 // the corresponding predicate and no more than twice as many applications of
2334 // any projection.
2335 //
2336 // Reference: https://wg21.link/alg.unique#:~:text=ranges::unique(I
2337 template <typename ForwardIterator,
2338 typename Comp = ranges::equal_to,
2339 typename Proj = std::identity,
2340 typename = internal::iterator_category_t<ForwardIterator>,
2341 typename = indirect_result_t<Comp&,
2342 projected<ForwardIterator, Proj>,
2343 projected<ForwardIterator, Proj>>>
2344 constexpr auto unique(ForwardIterator first,
2345 ForwardIterator last,
2346 Comp comp = {},
2347 Proj proj = {}) {
2348 return std::unique(first, last,
2349 internal::ProjectedBinaryPredicate(comp, proj, proj));
2350 }
2351
2352 // Let `E(i)` be `bool(invoke(comp, invoke(proj, *(i - 1)), invoke(proj, *i)))`.
2353 //
2354 // Effects: For a nonempty range, eliminates all but the first element from
2355 // every consecutive group of equivalent elements referred to by the iterator
2356 // `i` in the range `[begin(range) + 1, end(range))` for which `E(i)` is true.
2357 //
2358 // Returns: The end of the resulting range.
2359 //
2360 // Complexity: For nonempty ranges, exactly `size(range) - 1` applications of
2361 // the corresponding predicate and no more than twice as many applications of
2362 // any projection.
2363 //
2364 // Reference: https://wg21.link/alg.unique#:~:text=ranges::unique(R
2365 template <typename Range,
2366 typename Comp = ranges::equal_to,
2367 typename Proj = std::identity,
2368 typename = internal::range_category_t<Range>,
2369 typename = indirect_result_t<Comp&,
2370 projected<iterator_t<Range>, Proj>,
2371 projected<iterator_t<Range>, Proj>>>
2372 constexpr auto unique(Range&& range, Comp comp = {}, Proj proj = {}) {
2373 return ranges::unique(ranges::begin(range), ranges::end(range),
2374 std::move(comp), std::move(proj));
2375 }
2376
2377 // Let `E(i)` be `bool(invoke(comp, invoke(proj, *i), invoke(proj, *(i - 1))))`.
2378 //
2379 // Mandates: `*first` is writable to `result`.
2380 //
2381 // Preconditions: The ranges `[first, last)` and
2382 // `[result, result + (last - first))` do not overlap.
2383 //
2384 // Effects: Copies only the first element from every consecutive group of equal
2385 // elements referred to by the iterator `i` in the range `[first, last)` for
2386 // which `E(i)` holds.
2387 //
2388 // Returns: `result + N`.
2389 //
2390 // Complexity: Exactly `last - first - 1` applications of the corresponding
2391 // predicate and no more than twice as many applications of any projection.
2392 //
2393 // Reference: https://wg21.link/alg.unique#:~:text=ranges::unique_copy(I
2394 template <typename ForwardIterator,
2395 typename OutputIterator,
2396 typename Comp = ranges::equal_to,
2397 typename Proj = std::identity,
2398 typename = internal::iterator_category_t<ForwardIterator>,
2399 typename = internal::iterator_category_t<OutputIterator>>
2400 constexpr auto unique_copy(ForwardIterator first,
2401 ForwardIterator last,
2402 OutputIterator result,
2403 Comp comp = {},
2404 Proj proj = {}) {
2405 return std::unique_copy(first, last, result,
2406 internal::ProjectedBinaryPredicate(comp, proj, proj));
2407 }
2408
2409 // Let `E(i)` be `bool(invoke(comp, invoke(proj, *i), invoke(proj, *(i - 1))))`.
2410 //
2411 // Mandates: `*begin(range)` is writable to `result`.
2412 //
2413 // Preconditions: The ranges `range` and `[result, result + size(range))` do not
2414 // overlap.
2415 //
2416 // Effects: Copies only the first element from every consecutive group of equal
2417 // elements referred to by the iterator `i` in `range` for which `E(i)` holds.
2418 //
2419 // Returns: `result + N`.
2420 //
2421 // Complexity: Exactly `size(range) - 1` applications of the corresponding
2422 // predicate and no more than twice as many applications of any projection.
2423 //
2424 // Reference: https://wg21.link/alg.unique#:~:text=ranges::unique_copy(R
2425 template <typename Range,
2426 typename OutputIterator,
2427 typename Comp = ranges::equal_to,
2428 typename Proj = std::identity,
2429 typename = internal::range_category_t<Range>,
2430 typename = internal::iterator_category_t<OutputIterator>>
2431 constexpr auto unique_copy(Range&& range,
2432 OutputIterator result,
2433 Comp comp = {},
2434 Proj proj = {}) {
2435 return ranges::unique_copy(ranges::begin(range), ranges::end(range), result,
2436 std::move(comp), std::move(proj));
2437 }
2438
2439 // [alg.reverse] Reverse
2440 // Reference: https://wg21.link/alg.reverse
2441
2442 // Effects: For each non-negative integer `i < (last - first) / 2`, applies
2443 // `std::iter_swap` to all pairs of iterators `first + i, (last - i) - 1`.
2444 //
2445 // Returns: `last`.
2446 //
2447 // Complexity: Exactly `(last - first)/2` swaps.
2448 //
2449 // Reference: https://wg21.link/alg.reverse#:~:text=ranges::reverse(I
2450 template <typename BidirectionalIterator,
2451 typename = internal::iterator_category_t<BidirectionalIterator>>
reverse(BidirectionalIterator first,BidirectionalIterator last)2452 constexpr auto reverse(BidirectionalIterator first,
2453 BidirectionalIterator last) {
2454 std::reverse(first, last);
2455 return last;
2456 }
2457
2458 // Effects: For each non-negative integer `i < size(range) / 2`, applies
2459 // `std::iter_swap` to all pairs of iterators
2460 // `begin(range) + i, (end(range) - i) - 1`.
2461 //
2462 // Returns: `end(range)`.
2463 //
2464 // Complexity: Exactly `size(range)/2` swaps.
2465 //
2466 // Reference: https://wg21.link/alg.reverse#:~:text=ranges::reverse(R
2467 template <typename Range, typename = internal::range_category_t<Range>>
reverse(Range && range)2468 constexpr auto reverse(Range&& range) {
2469 return ranges::reverse(ranges::begin(range), ranges::end(range));
2470 }
2471
2472 // Let `N` be `last - first`.
2473 //
2474 // Preconditions: The ranges `[first, last)` and `[result, result + N)` do not
2475 // overlap.
2476 //
2477 // Effects: Copies the range `[first, last)` to the range `[result, result + N)`
2478 // such that for every non-negative integer `i < N` the following assignment
2479 // takes place: `*(result + N - 1 - i) = *(first + i)`.
2480 //
2481 // Returns: `result + N`.
2482 //
2483 // Complexity: Exactly `N` assignments.
2484 //
2485 // Reference: https://wg21.link/alg.reverse#:~:text=ranges::reverse_copy(I
2486 template <typename BidirectionalIterator,
2487 typename OutputIterator,
2488 typename = internal::iterator_category_t<BidirectionalIterator>,
2489 typename = internal::iterator_category_t<OutputIterator>>
reverse_copy(BidirectionalIterator first,BidirectionalIterator last,OutputIterator result)2490 constexpr auto reverse_copy(BidirectionalIterator first,
2491 BidirectionalIterator last,
2492 OutputIterator result) {
2493 return std::reverse_copy(first, last, result);
2494 }
2495
2496 // Let `N` be `size(range)`.
2497 //
2498 // Preconditions: The ranges `range` and `[result, result + N)` do not
2499 // overlap.
2500 //
2501 // Effects: Copies `range` to the range `[result, result + N)` such that for
2502 // every non-negative integer `i < N` the following assignment takes place:
2503 // `*(result + N - 1 - i) = *(begin(range) + i)`.
2504 //
2505 // Returns: `result + N`.
2506 //
2507 // Complexity: Exactly `N` assignments.
2508 //
2509 // Reference: https://wg21.link/alg.reverse#:~:text=ranges::reverse_copy(R
2510 template <typename Range,
2511 typename OutputIterator,
2512 typename = internal::range_category_t<Range>,
2513 typename = internal::iterator_category_t<OutputIterator>>
reverse_copy(Range && range,OutputIterator result)2514 constexpr auto reverse_copy(Range&& range, OutputIterator result) {
2515 return ranges::reverse_copy(ranges::begin(range), ranges::end(range), result);
2516 }
2517
2518 // [alg.rotate] Rotate
2519 // Reference: https://wg21.link/alg.rotate
2520
2521 // Preconditions: `[first, middle)` and `[middle, last)` are valid ranges.
2522 //
2523 // Effects: For each non-negative integer `i < (last - first)`, places the
2524 // element from the position `first + i` into position
2525 // `first + (i + (last - middle)) % (last - first)`.
2526 //
2527 // Returns: `first + (last - middle)`.
2528 //
2529 // Complexity: At most `last - first` swaps.
2530 //
2531 // Reference: https://wg21.link/alg.rotate#:~:text=ranges::rotate(I
2532 template <typename ForwardIterator,
2533 typename = internal::iterator_category_t<ForwardIterator>>
rotate(ForwardIterator first,ForwardIterator middle,ForwardIterator last)2534 constexpr auto rotate(ForwardIterator first,
2535 ForwardIterator middle,
2536 ForwardIterator last) {
2537 return std::rotate(first, middle, last);
2538 }
2539
2540 // Preconditions: `[begin(range), middle)` and `[middle, end(range))` are valid
2541 // ranges.
2542 //
2543 // Effects: For each non-negative integer `i < size(range)`, places the element
2544 // from the position `begin(range) + i` into position
2545 // `begin(range) + (i + (end(range) - middle)) % size(range)`.
2546 //
2547 // Returns: `begin(range) + (end(range) - middle)`.
2548 //
2549 // Complexity: At most `size(range)` swaps.
2550 //
2551 // Reference: https://wg21.link/alg.rotate#:~:text=ranges::rotate(R
2552 template <typename Range, typename = internal::range_category_t<Range>>
rotate(Range && range,iterator_t<Range> middle)2553 constexpr auto rotate(Range&& range, iterator_t<Range> middle) {
2554 return ranges::rotate(ranges::begin(range), middle, ranges::end(range));
2555 }
2556
2557 // Let `N` be `last - first`.
2558 //
2559 // Preconditions: `[first, middle)` and `[middle, last)` are valid ranges. The
2560 // ranges `[first, last)` and `[result, result + N)` do not overlap.
2561 //
2562 // Effects: Copies the range `[first, last)` to the range `[result, result + N)`
2563 // such that for each non-negative integer `i < N` the following assignment
2564 // takes place: `*(result + i) = *(first + (i + (middle - first)) % N)`.
2565 //
2566 // Returns: `result + N`.
2567 //
2568 // Complexity: Exactly `N` assignments.
2569 //
2570 // Reference: https://wg21.link/alg.rotate#:~:text=ranges::rotate_copy(I
2571 template <typename ForwardIterator,
2572 typename OutputIterator,
2573 typename = internal::iterator_category_t<ForwardIterator>,
2574 typename = internal::iterator_category_t<OutputIterator>>
rotate_copy(ForwardIterator first,ForwardIterator middle,ForwardIterator last,OutputIterator result)2575 constexpr auto rotate_copy(ForwardIterator first,
2576 ForwardIterator middle,
2577 ForwardIterator last,
2578 OutputIterator result) {
2579 return std::rotate_copy(first, middle, last, result);
2580 }
2581
2582 // Let `N` be `size(range)`.
2583 //
2584 // Preconditions: `[begin(range), middle)` and `[middle, end(range))` are valid
2585 // ranges. The ranges `range` and `[result, result + N)` do not overlap.
2586 //
2587 // Effects: Copies `range` to the range `[result, result + N)` such that for
2588 // each non-negative integer `i < N` the following assignment takes place:
2589 // `*(result + i) = *(begin(range) + (i + (middle - begin(range))) % N)`.
2590 //
2591 // Returns: `result + N`.
2592 //
2593 // Complexity: Exactly `N` assignments.
2594 //
2595 // Reference: https://wg21.link/alg.rotate#:~:text=ranges::rotate_copy(R
2596 template <typename Range,
2597 typename OutputIterator,
2598 typename = internal::range_category_t<Range>,
2599 typename = internal::iterator_category_t<OutputIterator>>
rotate_copy(Range && range,iterator_t<Range> middle,OutputIterator result)2600 constexpr auto rotate_copy(Range&& range,
2601 iterator_t<Range> middle,
2602 OutputIterator result) {
2603 return ranges::rotate_copy(ranges::begin(range), middle, ranges::end(range),
2604 result);
2605 }
2606
2607 // [alg.random.sample] Sample
2608 // Reference: https://wg21.link/alg.random.sample
2609
2610 // Currently not implemented due to lack of std::sample in C++14.
2611 // TODO(crbug.com/1071094): Consider implementing a hand-rolled version.
2612
2613 // [alg.random.shuffle] Shuffle
2614 // Reference: https://wg21.link/alg.random.shuffle
2615
2616 // Preconditions: The type `std::remove_reference_t<UniformRandomBitGenerator>`
2617 // meets the uniform random bit generator requirements.
2618 //
2619 // Effects: Permutes the elements in the range `[first, last)` such that each
2620 // possible permutation of those elements has equal probability of appearance.
2621 //
2622 // Returns: `last`.
2623 //
2624 // Complexity: Exactly `(last - first) - 1` swaps.
2625 //
2626 // Remarks: To the extent that the implementation of this function makes use of
2627 // random numbers, the object referenced by g shall serve as the
2628 // implementation's source of randomness.
2629 //
2630 // Reference: https://wg21.link/alg.random.shuffle#:~:text=ranges::shuffle(I
2631 template <typename RandomAccessIterator,
2632 typename UniformRandomBitGenerator,
2633 typename = internal::iterator_category_t<RandomAccessIterator>>
shuffle(RandomAccessIterator first,RandomAccessIterator last,UniformRandomBitGenerator && g)2634 constexpr auto shuffle(RandomAccessIterator first,
2635 RandomAccessIterator last,
2636 UniformRandomBitGenerator&& g) {
2637 std::shuffle(first, last, std::forward<UniformRandomBitGenerator>(g));
2638 return last;
2639 }
2640
2641 // Preconditions: The type `std::remove_reference_t<UniformRandomBitGenerator>`
2642 // meets the uniform random bit generator requirements.
2643 //
2644 // Effects: Permutes the elements in `range` such that each possible permutation
2645 // of those elements has equal probability of appearance.
2646 //
2647 // Returns: `end(range)`.
2648 //
2649 // Complexity: Exactly `size(range) - 1` swaps.
2650 //
2651 // Remarks: To the extent that the implementation of this function makes use of
2652 // random numbers, the object referenced by g shall serve as the
2653 // implementation's source of randomness.
2654 //
2655 // Reference: https://wg21.link/alg.random.shuffle#:~:text=ranges::shuffle(R
2656 template <typename Range,
2657 typename UniformRandomBitGenerator,
2658 typename = internal::range_category_t<Range>>
shuffle(Range && range,UniformRandomBitGenerator && g)2659 constexpr auto shuffle(Range&& range, UniformRandomBitGenerator&& g) {
2660 return ranges::shuffle(ranges::begin(range), ranges::end(range),
2661 std::forward<UniformRandomBitGenerator>(g));
2662 }
2663
2664 // [alg.nonmodifying] Sorting and related operations
2665 // Reference: https://wg21.link/alg.sorting
2666
2667 // [alg.sort] Sorting
2668 // Reference: https://wg21.link/alg.sort
2669
2670 // [sort] sort
2671 // Reference: https://wg21.link/sort
2672
2673 // Effects: Sorts the elements in the range `[first, last)` with respect to
2674 // `comp` and `proj`.
2675 //
2676 // Returns: `last`.
2677 //
2678 // Complexity: Let `N` be `last - first`. `O(N log N)` comparisons and
2679 // projections.
2680 //
2681 // Reference: https://wg21.link/sort#:~:text=ranges::sort(I
2682 template <typename RandomAccessIterator,
2683 typename Comp = ranges::less,
2684 typename Proj = std::identity,
2685 typename = internal::iterator_category_t<RandomAccessIterator>,
2686 typename = indirect_result_t<Comp&,
2687 projected<RandomAccessIterator, Proj>,
2688 projected<RandomAccessIterator, Proj>>>
2689 constexpr auto sort(RandomAccessIterator first,
2690 RandomAccessIterator last,
2691 Comp comp = {},
2692 Proj proj = {}) {
2693 std::sort(first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
2694 return last;
2695 }
2696
2697 // Effects: Sorts the elements in `range` with respect to `comp` and `proj`.
2698 //
2699 // Returns: `end(range)`.
2700 //
2701 // Complexity: Let `N` be `size(range)`. `O(N log N)` comparisons and
2702 // projections.
2703 //
2704 // Reference: https://wg21.link/sort#:~:text=ranges::sort(R
2705 template <typename Range,
2706 typename Comp = ranges::less,
2707 typename Proj = std::identity,
2708 typename = internal::range_category_t<Range>,
2709 typename = indirect_result_t<Comp&,
2710 projected<iterator_t<Range>, Proj>,
2711 projected<iterator_t<Range>, Proj>>>
2712 constexpr auto sort(Range&& range, Comp comp = {}, Proj proj = {}) {
2713 return ranges::sort(ranges::begin(range), ranges::end(range), std::move(comp),
2714 std::move(proj));
2715 }
2716
2717 // [stable.sort] stable_sort
2718 // Reference: https://wg21.link/stable.sort
2719
2720 // Effects: Sorts the elements in the range `[first, last)` with respect to
2721 // `comp` and `proj`.
2722 //
2723 // Returns: `last`.
2724 //
2725 // Complexity: Let `N` be `last - first`. If enough extra memory is available,
2726 // `N log (N)` comparisons. Otherwise, at most `N log^2 (N)` comparisons. In
2727 // either case, twice as many projections as the number of comparisons.
2728 //
2729 // Remarks: Stable.
2730 //
2731 // Reference: https://wg21.link/stable.sort#:~:text=ranges::stable_sort(I
2732 template <typename RandomAccessIterator,
2733 typename Comp = ranges::less,
2734 typename Proj = std::identity,
2735 typename = internal::iterator_category_t<RandomAccessIterator>,
2736 typename = indirect_result_t<Comp&,
2737 projected<RandomAccessIterator, Proj>,
2738 projected<RandomAccessIterator, Proj>>>
2739 constexpr auto stable_sort(RandomAccessIterator first,
2740 RandomAccessIterator last,
2741 Comp comp = {},
2742 Proj proj = {}) {
2743 std::stable_sort(first, last,
2744 internal::ProjectedBinaryPredicate(comp, proj, proj));
2745 return last;
2746 }
2747
2748 // Effects: Sorts the elements in `range` with respect to `comp` and `proj`.
2749 //
2750 // Returns: `end(rang)`.
2751 //
2752 // Complexity: Let `N` be `size(range)`. If enough extra memory is available,
2753 // `N log (N)` comparisons. Otherwise, at most `N log^2 (N)` comparisons. In
2754 // either case, twice as many projections as the number of comparisons.
2755 //
2756 // Remarks: Stable.
2757 //
2758 // Reference: https://wg21.link/stable.sort#:~:text=ranges::stable_sort(R
2759 template <typename Range,
2760 typename Comp = ranges::less,
2761 typename Proj = std::identity,
2762 typename = internal::range_category_t<Range>,
2763 typename = indirect_result_t<Comp&,
2764 projected<iterator_t<Range>, Proj>,
2765 projected<iterator_t<Range>, Proj>>>
2766 constexpr auto stable_sort(Range&& range, Comp comp = {}, Proj proj = {}) {
2767 return ranges::stable_sort(ranges::begin(range), ranges::end(range),
2768 std::move(comp), std::move(proj));
2769 }
2770
2771 // [partial.sort] partial_sort
2772 // Reference: https://wg21.link/partial.sort
2773
2774 // Preconditions: `[first, middle)` and `[middle, last)` are valid ranges.
2775 //
2776 // Effects: Places the first `middle - first` elements from the range
2777 // `[first, last)` as sorted with respect to `comp` and `proj` into the range
2778 // `[first, middle)`. The rest of the elements in the range `[middle, last)` are
2779 // placed in an unspecified order.
2780 //
2781 // Returns: `last`.
2782 //
2783 // Complexity: Approximately `(last - first) * log(middle - first)` comparisons,
2784 // and twice as many projections.
2785 //
2786 // Reference: https://wg21.link/partial.sort#:~:text=ranges::partial_sort(I
2787 template <typename RandomAccessIterator,
2788 typename Comp = ranges::less,
2789 typename Proj = std::identity,
2790 typename = internal::iterator_category_t<RandomAccessIterator>,
2791 typename = indirect_result_t<Comp&,
2792 projected<RandomAccessIterator, Proj>,
2793 projected<RandomAccessIterator, Proj>>>
2794 constexpr auto partial_sort(RandomAccessIterator first,
2795 RandomAccessIterator middle,
2796 RandomAccessIterator last,
2797 Comp comp = {},
2798 Proj proj = {}) {
2799 std::partial_sort(first, middle, last,
2800 internal::ProjectedBinaryPredicate(comp, proj, proj));
2801 return last;
2802 }
2803
2804 // Preconditions: `[begin(range), middle)` and `[middle, end(range))` are valid
2805 // ranges.
2806 //
2807 // Effects: Places the first `middle - begin(range)` elements from `range` as
2808 // sorted with respect to `comp` and `proj` into the range
2809 // `[begin(range), middle)`. The rest of the elements in the range
2810 // `[middle, end(range))` are placed in an unspecified order.
2811 //
2812 // Returns: `end(range)`.
2813 //
2814 // Complexity: Approximately `size(range) * log(middle - begin(range))`
2815 // comparisons, and twice as many projections.
2816 //
2817 // Reference: https://wg21.link/partial.sort#:~:text=ranges::partial_sort(R
2818 template <typename Range,
2819 typename Comp = ranges::less,
2820 typename Proj = std::identity,
2821 typename = internal::range_category_t<Range>,
2822 typename = indirect_result_t<Comp&,
2823 projected<iterator_t<Range>, Proj>,
2824 projected<iterator_t<Range>, Proj>>>
2825 constexpr auto partial_sort(Range&& range,
2826 iterator_t<Range> middle,
2827 Comp comp = {},
2828 Proj proj = {}) {
2829 return ranges::partial_sort(ranges::begin(range), middle, ranges::end(range),
2830 std::move(comp), std::move(proj));
2831 }
2832
2833 // [partial.sort.copy] partial_sort_copy
2834 // Reference: https://wg21.link/partial.sort.copy
2835
2836 // Let `N` be `min(last - first, result_last - result_first)`.
2837 //
2838 // Preconditions: For iterators `a1` and `b1` in `[first, last)`, and iterators
2839 // `x2` and `y2` in `[result_first, result_last)`, after evaluating the
2840 // assignment `*y2 = *b1`, let `E` be the value of `bool(invoke(comp,
2841 // invoke(proj1, *a1), invoke(proj2, *y2)))`. Then, after evaluating the
2842 // assignment `*x2 = *a1`, `E` is equal to `bool(invoke(comp, invoke(proj2,
2843 // *x2), invoke(proj2, *y2)))`.
2844 //
2845 // Effects: Places the first `N` elements as sorted with respect to `comp` and
2846 // `proj2` into the range `[result_first, result_first + N)`.
2847 //
2848 // Returns: `result_first + N`.
2849 //
2850 // Complexity: Approximately `(last - first) * log N` comparisons, and twice as
2851 // many projections.
2852 //
2853 // Reference:
2854 // https://wg21.link/partial.sort.copy#:~:text=ranges::partial_sort_copy(I1
2855 template <typename InputIterator,
2856 typename RandomAccessIterator,
2857 typename Comp = ranges::less,
2858 typename Proj1 = std::identity,
2859 typename Proj2 = std::identity,
2860 typename = internal::iterator_category_t<InputIterator>,
2861 typename = internal::iterator_category_t<RandomAccessIterator>,
2862 typename = indirect_result_t<Comp&,
2863 projected<InputIterator, Proj1>,
2864 projected<RandomAccessIterator, Proj2>>,
2865 typename = indirect_result_t<Comp&,
2866 projected<RandomAccessIterator, Proj2>,
2867 projected<InputIterator, Proj1>>>
2868 constexpr auto partial_sort_copy(InputIterator first,
2869 InputIterator last,
2870 RandomAccessIterator result_first,
2871 RandomAccessIterator result_last,
2872 Comp comp = {},
2873 Proj1 proj1 = {},
2874 Proj2 proj2 = {}) {
2875 // Needs to opt-in to all permutations, since std::partial_sort_copy expects
2876 // comp(proj2(lhs), proj1(rhs)) to compile.
2877 return std::partial_sort_copy(
2878 first, last, result_first, result_last,
2879 internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
2880 }
2881
2882 // Let `N` be `min(size(range), size(result_range))`.
2883 //
2884 // Preconditions: For iterators `a1` and `b1` in `range`, and iterators
2885 // `x2` and `y2` in `result_range`, after evaluating the assignment
2886 // `*y2 = *b1`, let `E` be the value of
2887 // `bool(invoke(comp, invoke(proj1, *a1), invoke(proj2, *y2)))`. Then, after
2888 // evaluating the assignment `*x2 = *a1`, `E` is equal to
2889 // `bool(invoke(comp, invoke(proj2, *x2), invoke(proj2, *y2)))`.
2890 //
2891 // Effects: Places the first `N` elements as sorted with respect to `comp` and
2892 // `proj2` into the range `[begin(result_range), begin(result_range) + N)`.
2893 //
2894 // Returns: `begin(result_range) + N`.
2895 //
2896 // Complexity: Approximately `size(range) * log N` comparisons, and twice as
2897 // many projections.
2898 //
2899 // Reference:
2900 // https://wg21.link/partial.sort.copy#:~:text=ranges::partial_sort_copy(R1
2901 template <typename Range1,
2902 typename Range2,
2903 typename Comp = ranges::less,
2904 typename Proj1 = std::identity,
2905 typename Proj2 = std::identity,
2906 typename = internal::range_category_t<Range1>,
2907 typename = internal::range_category_t<Range2>,
2908 typename = indirect_result_t<Comp&,
2909 projected<iterator_t<Range1>, Proj1>,
2910 projected<iterator_t<Range2>, Proj2>>,
2911 typename = indirect_result_t<Comp&,
2912 projected<iterator_t<Range2>, Proj2>,
2913 projected<iterator_t<Range1>, Proj1>>>
2914 constexpr auto partial_sort_copy(Range1&& range,
2915 Range2&& result_range,
2916 Comp comp = {},
2917 Proj1 proj1 = {},
2918 Proj2 proj2 = {}) {
2919 return ranges::partial_sort_copy(ranges::begin(range), ranges::end(range),
2920 ranges::begin(result_range),
2921 ranges::end(result_range), std::move(comp),
2922 std::move(proj1), std::move(proj2));
2923 }
2924
2925 // [is.sorted] is_sorted
2926 // Reference: https://wg21.link/is.sorted
2927
2928 // Returns: The last iterator `i` in `[first, last]` for which the range
2929 // `[first, i)` is sorted with respect to `comp` and `proj`.
2930 //
2931 // Complexity: Linear.
2932 //
2933 // Reference: https://wg21.link/is.sorted#:~:text=ranges::is_sorted_until(I
2934 template <typename ForwardIterator,
2935 typename Comp = ranges::less,
2936 typename Proj = std::identity,
2937 typename = internal::iterator_category_t<ForwardIterator>,
2938 typename = indirect_result_t<Comp&,
2939 projected<ForwardIterator, Proj>,
2940 projected<ForwardIterator, Proj>>>
2941 constexpr auto is_sorted_until(ForwardIterator first,
2942 ForwardIterator last,
2943 Comp comp = {},
2944 Proj proj = {}) {
2945 // Implementation inspired by cppreference.com:
2946 // https://en.cppreference.com/w/cpp/algorithm/is_sorted_until
2947 //
2948 // A reimplementation is required, because std::is_sorted_until is not
2949 // constexpr prior to C++20. Once we have C++20, we should switch to standard
2950 // library implementation.
2951 if (first == last)
2952 return last;
2953
2954 for (ForwardIterator next = first; ++next != last; ++first) {
2955 if (std::invoke(comp, std::invoke(proj, *next),
2956 std::invoke(proj, *first))) {
2957 return next;
2958 }
2959 }
2960
2961 return last;
2962 }
2963
2964 // Returns: The last iterator `i` in `[begin(range), end(range)]` for which the
2965 // range `[begin(range), i)` is sorted with respect to `comp` and `proj`.
2966 //
2967 // Complexity: Linear.
2968 //
2969 // Reference: https://wg21.link/is.sorted#:~:text=ranges::is_sorted_until(R
2970 template <typename Range,
2971 typename Comp = ranges::less,
2972 typename Proj = std::identity,
2973 typename = internal::range_category_t<Range>,
2974 typename = indirect_result_t<Comp&,
2975 projected<iterator_t<Range>, Proj>,
2976 projected<iterator_t<Range>, Proj>>>
2977 constexpr auto is_sorted_until(Range&& range, Comp comp = {}, Proj proj = {}) {
2978 return ranges::is_sorted_until(ranges::begin(range), ranges::end(range),
2979 std::move(comp), std::move(proj));
2980 }
2981
2982 // Returns: Whether the range `[first, last)` is sorted with respect to `comp`
2983 // and `proj`.
2984 //
2985 // Complexity: Linear.
2986 //
2987 // Reference: https://wg21.link/is.sorted#:~:text=ranges::is_sorted(I
2988 template <typename ForwardIterator,
2989 typename Comp = ranges::less,
2990 typename Proj = std::identity,
2991 typename = internal::iterator_category_t<ForwardIterator>,
2992 typename = indirect_result_t<Comp&,
2993 projected<ForwardIterator, Proj>,
2994 projected<ForwardIterator, Proj>>>
2995 constexpr auto is_sorted(ForwardIterator first,
2996 ForwardIterator last,
2997 Comp comp = {},
2998 Proj proj = {}) {
2999 return ranges::is_sorted_until(first, last, std::move(comp),
3000 std::move(proj)) == last;
3001 }
3002
3003 // Returns: Whether `range` is sorted with respect to `comp` and `proj`.
3004 //
3005 // Complexity: Linear.
3006 //
3007 // Reference: https://wg21.link/is.sorted#:~:text=ranges::is_sorted(R
3008 template <typename Range,
3009 typename Comp = ranges::less,
3010 typename Proj = std::identity,
3011 typename = internal::range_category_t<Range>,
3012 typename = indirect_result_t<Comp&,
3013 projected<iterator_t<Range>, Proj>,
3014 projected<iterator_t<Range>, Proj>>>
3015 constexpr auto is_sorted(Range&& range, Comp comp = {}, Proj proj = {}) {
3016 return ranges::is_sorted(ranges::begin(range), ranges::end(range),
3017 std::move(comp), std::move(proj));
3018 }
3019
3020 // [alg.nth.element] Nth element
3021 // Reference: https://wg21.link/alg.nth.element
3022
3023 // Preconditions: `[first, nth)` and `[nth, last)` are valid ranges.
3024 //
3025 // Effects: After `nth_element` the element in the position pointed to by `nth`
3026 // is the element that would be in that position if the whole range were sorted
3027 // with respect to `comp` and `proj`, unless `nth == last`. Also for every
3028 // iterator `i` in the range `[first, nth)` and every iterator `j` in the range
3029 // `[nth, last)` it holds that:
3030 // `bool(invoke(comp, invoke(proj, *j), invoke(proj, *i)))` is false.
3031 //
3032 // Returns: `last`.
3033 //
3034 // Complexity: Linear on average.
3035 //
3036 // Reference: https://wg21.link/alg.nth.element#:~:text=ranges::nth_element(I
3037 template <typename RandomAccessIterator,
3038 typename Comp = ranges::less,
3039 typename Proj = std::identity,
3040 typename = internal::iterator_category_t<RandomAccessIterator>,
3041 typename = indirect_result_t<Comp&,
3042 projected<RandomAccessIterator, Proj>,
3043 projected<RandomAccessIterator, Proj>>>
3044 constexpr auto nth_element(RandomAccessIterator first,
3045 RandomAccessIterator nth,
3046 RandomAccessIterator last,
3047 Comp comp = {},
3048 Proj proj = {}) {
3049 std::nth_element(first, nth, last,
3050 internal::ProjectedBinaryPredicate(comp, proj, proj));
3051 return last;
3052 }
3053
3054 // Preconditions: `[begin(range), nth)` and `[nth, end(range))` are valid
3055 // ranges.
3056 //
3057 // Effects: After `nth_element` the element in the position pointed to by `nth`
3058 // is the element that would be in that position if the whole range were sorted
3059 // with respect to `comp` and `proj`, unless `nth == end(range)`. Also for every
3060 // iterator `i` in the range `[begin(range), nth)` and every iterator `j` in the
3061 // range `[nth, end(range))` it holds that:
3062 // `bool(invoke(comp, invoke(proj, *j), invoke(proj, *i)))` is false.
3063 //
3064 // Returns: `end(range)`.
3065 //
3066 // Complexity: Linear on average.
3067 //
3068 // Reference: https://wg21.link/alg.nth.element#:~:text=ranges::nth_element(R
3069 template <typename Range,
3070 typename Comp = ranges::less,
3071 typename Proj = std::identity,
3072 typename = internal::range_category_t<Range>,
3073 typename = indirect_result_t<Comp&,
3074 projected<iterator_t<Range>, Proj>,
3075 projected<iterator_t<Range>, Proj>>>
3076 constexpr auto nth_element(Range&& range,
3077 iterator_t<Range> nth,
3078 Comp comp = {},
3079 Proj proj = {}) {
3080 return ranges::nth_element(ranges::begin(range), nth, ranges::end(range),
3081 std::move(comp), std::move(proj));
3082 }
3083
3084 // [alg.binary.search] Binary search
3085 // Reference: https://wg21.link/alg.binary.search
3086
3087 // [lower.bound] lower_bound
3088 // Reference: https://wg21.link/lower.bound
3089
3090 // Preconditions: The elements `e` of `[first, last)` are partitioned with
3091 // respect to the expression `bool(invoke(comp, invoke(proj, e), value))`.
3092 //
3093 // Returns: The furthermost iterator `i` in the range `[first, last]` such that
3094 // for every iterator `j` in the range `[first, i)`,
3095 // `bool(invoke(comp, invoke(proj, *j), value))` is true.
3096 //
3097 // Complexity: At most `log_2(last - first) + O(1)` comparisons and projections.
3098 //
3099 // Reference: https://wg21.link/lower.bound#:~:text=ranges::lower_bound(I
3100 template <typename ForwardIterator,
3101 typename T,
3102 typename Comp = ranges::less,
3103 typename Proj = std::identity,
3104 typename = internal::iterator_category_t<ForwardIterator>>
3105 constexpr auto lower_bound(ForwardIterator first,
3106 ForwardIterator last,
3107 const T& value,
3108 Comp comp = {},
3109 Proj proj = {}) {
3110 // The second arg is guaranteed to be `value`, so we'll simply apply the
3111 // std::identity projection.
3112 std::identity value_proj;
3113 return std::lower_bound(
3114 first, last, value,
3115 internal::ProjectedBinaryPredicate(comp, proj, value_proj));
3116 }
3117
3118 // Preconditions: The elements `e` of `range` are partitioned with respect to
3119 // the expression `bool(invoke(comp, invoke(proj, e), value))`.
3120 //
3121 // Returns: The furthermost iterator `i` in the range
3122 // `[begin(range), end(range)]` such that for every iterator `j` in the range
3123 // `[begin(range), i)`, `bool(invoke(comp, invoke(proj, *j), value))` is true.
3124 //
3125 // Complexity: At most `log_2(size(range)) + O(1)` comparisons and projections.
3126 //
3127 // Reference: https://wg21.link/lower.bound#:~:text=ranges::lower_bound(R
3128 template <typename Range,
3129 typename T,
3130 typename Comp = ranges::less,
3131 typename Proj = std::identity,
3132 typename = internal::range_category_t<Range>>
3133 constexpr auto lower_bound(Range&& range,
3134 const T& value,
3135 Comp comp = {},
3136 Proj proj = {}) {
3137 return ranges::lower_bound(ranges::begin(range), ranges::end(range), value,
3138 std::move(comp), std::move(proj));
3139 }
3140
3141 // [upper.bound] upper_bound
3142 // Reference: https://wg21.link/upper.bound
3143
3144 // Preconditions: The elements `e` of `[first, last)` are partitioned with
3145 // respect to the expression `!bool(invoke(comp, value, invoke(proj, e)))`.
3146 //
3147 // Returns: The furthermost iterator `i` in the range `[first, last]` such that
3148 // for every iterator `j` in the range `[first, i)`,
3149 // `!bool(invoke(comp, value, invoke(proj, *j)))` is true.
3150 //
3151 // Complexity: At most `log_2(last - first) + O(1)` comparisons and projections.
3152 //
3153 // Reference: https://wg21.link/upper.bound#:~:text=ranges::upper_bound(I
3154 template <typename ForwardIterator,
3155 typename T,
3156 typename Comp = ranges::less,
3157 typename Proj = std::identity,
3158 typename = internal::iterator_category_t<ForwardIterator>>
3159 constexpr auto upper_bound(ForwardIterator first,
3160 ForwardIterator last,
3161 const T& value,
3162 Comp comp = {},
3163 Proj proj = {}) {
3164 // The first arg is guaranteed to be `value`, so we'll simply apply the
3165 // std::identity projection.
3166 std::identity value_proj;
3167 return std::upper_bound(
3168 first, last, value,
3169 internal::ProjectedBinaryPredicate(comp, value_proj, proj));
3170 }
3171
3172 // Preconditions: The elements `e` of `range` are partitioned with
3173 // respect to the expression `!bool(invoke(comp, value, invoke(proj, e)))`.
3174 //
3175 // Returns: The furthermost iterator `i` in the range
3176 // `[begin(range), end(range)]` such that for every iterator `j` in the range
3177 // `[begin(range), i)`, `!bool(invoke(comp, value, invoke(proj, *j)))` is true.
3178 //
3179 // Complexity: At most `log_2(size(range)) + O(1)` comparisons and projections.
3180 //
3181 // Reference: https://wg21.link/upper.bound#:~:text=ranges::upper_bound(R
3182 template <typename Range,
3183 typename T,
3184 typename Comp = ranges::less,
3185 typename Proj = std::identity,
3186 typename = internal::range_category_t<Range>>
3187 constexpr auto upper_bound(Range&& range,
3188 const T& value,
3189 Comp comp = {},
3190 Proj proj = {}) {
3191 return ranges::upper_bound(ranges::begin(range), ranges::end(range), value,
3192 std::move(comp), std::move(proj));
3193 }
3194
3195 // [equal.range] equal_range
3196 // Reference: https://wg21.link/equal.range
3197
3198 // Preconditions: The elements `e` of `[first, last)` are partitioned with
3199 // respect to the expressions `bool(invoke(comp, invoke(proj, e), value))` and
3200 // `!bool(invoke(comp, value, invoke(proj, e)))`.
3201 //
3202 // Returns: `{ranges::lower_bound(first, last, value, comp, proj),
3203 // ranges::upper_bound(first, last, value, comp, proj)}`.
3204 //
3205 // Complexity: At most 2 ∗ log_2(last - first) + O(1) comparisons and
3206 // projections.
3207 //
3208 // Reference: https://wg21.link/equal.range#:~:text=ranges::equal_range(I
3209 template <typename ForwardIterator,
3210 typename T,
3211 typename Comp = ranges::less,
3212 typename Proj = std::identity,
3213 typename = internal::iterator_category_t<ForwardIterator>>
3214 constexpr auto equal_range(ForwardIterator first,
3215 ForwardIterator last,
3216 const T& value,
3217 Comp comp = {},
3218 Proj proj = {}) {
3219 // Note: This does not dispatch to std::equal_range, as otherwise it would not
3220 // be possible to prevent applying `proj` to `value`, which can result in
3221 // unintended behavior.
3222 return std::make_pair(ranges::lower_bound(first, last, value, comp, proj),
3223 ranges::upper_bound(first, last, value, comp, proj));
3224 }
3225
3226 // Preconditions: The elements `e` of `range` are partitioned with
3227 // respect to the expressions `bool(invoke(comp, invoke(proj, e), value))` and
3228 // `!bool(invoke(comp, value, invoke(proj, e)))`.
3229 //
3230 // Returns: `{ranges::lower_bound(range, value, comp, proj),
3231 // ranges::upper_bound(range, value, comp, proj)}`.
3232 //
3233 // Complexity: At most 2 ∗ log_2(size(range)) + O(1) comparisons and
3234 // projections.
3235 //
3236 // Reference: https://wg21.link/equal.range#:~:text=ranges::equal_range(R
3237 template <typename Range,
3238 typename T,
3239 typename Comp = ranges::less,
3240 typename Proj = std::identity,
3241 typename = internal::range_category_t<Range>>
3242 constexpr auto equal_range(Range&& range,
3243 const T& value,
3244 Comp comp = {},
3245 Proj proj = {}) {
3246 return ranges::equal_range(ranges::begin(range), ranges::end(range), value,
3247 std::move(comp), std::move(proj));
3248 }
3249
3250 // [binary.search] binary_search
3251 // Reference: https://wg21.link/binary.search
3252
3253 // Preconditions: The elements `e` of `[first, last)` are partitioned with
3254 // respect to the expressions `bool(invoke(comp, invoke(proj, e), value))` and
3255 // `!bool(invoke(comp, value, invoke(proj, e)))`.
3256 //
3257 // Returns: `true` if and only if for some iterator `i` in the range
3258 // `[first, last)`, `!bool(invoke(comp, invoke(proj, *i), value)) &&
3259 // !bool(invoke(comp, value, invoke(proj, *i)))` is true.
3260 //
3261 // Complexity: At most `log_2(last - first) + O(1)` comparisons and projections.
3262 //
3263 // Reference: https://wg21.link/binary.search#:~:text=ranges::binary_search(I
3264 template <typename ForwardIterator,
3265 typename T,
3266 typename Comp = ranges::less,
3267 typename Proj = std::identity,
3268 typename = internal::iterator_category_t<ForwardIterator>>
3269 constexpr auto binary_search(ForwardIterator first,
3270 ForwardIterator last,
3271 const T& value,
3272 Comp comp = {},
3273 Proj proj = {}) {
3274 first = ranges::lower_bound(first, last, value, comp, proj);
3275 return first != last && !std::invoke(comp, value, std::invoke(proj, *first));
3276 }
3277
3278 // Preconditions: The elements `e` of `range` are partitioned with
3279 // respect to the expressions `bool(invoke(comp, invoke(proj, e), value))` and
3280 // `!bool(invoke(comp, value, invoke(proj, e)))`.
3281 //
3282 // Returns: `true` if and only if for some iterator `i` in `range`
3283 // `!bool(invoke(comp, invoke(proj, *i), value)) &&
3284 // !bool(invoke(comp, value, invoke(proj, *i)))` is true.
3285 //
3286 // Complexity: At most `log_2(size(range)) + O(1)` comparisons and projections.
3287 //
3288 // Reference: https://wg21.link/binary.search#:~:text=ranges::binary_search(R
3289 template <typename Range,
3290 typename T,
3291 typename Comp = ranges::less,
3292 typename Proj = std::identity,
3293 typename = internal::range_category_t<Range>>
3294 constexpr auto binary_search(Range&& range,
3295 const T& value,
3296 Comp comp = {},
3297 Proj proj = {}) {
3298 return ranges::binary_search(ranges::begin(range), ranges::end(range), value,
3299 std::move(comp), std::move(proj));
3300 }
3301
3302 // [alg.partitions] Partitions
3303 // Reference: https://wg21.link/alg.partitions
3304
3305 // Returns: `true` if and only if the elements `e` of `[first, last)` are
3306 // partitioned with respect to the expression
3307 // `bool(invoke(pred, invoke(proj, e)))`.
3308 //
3309 // Complexity: Linear. At most `last - first` applications of `pred` and `proj`.
3310 //
3311 // Reference: https://wg21.link/alg.partitions#:~:text=ranges::is_partitioned(I
3312 template <typename ForwardIterator,
3313 typename Pred,
3314 typename Proj = std::identity,
3315 typename = internal::iterator_category_t<ForwardIterator>>
3316 constexpr auto is_partitioned(ForwardIterator first,
3317 ForwardIterator last,
3318 Pred pred,
3319 Proj proj = {}) {
3320 return std::is_partitioned(first, last,
3321 internal::ProjectedUnaryPredicate(pred, proj));
3322 }
3323
3324 // Returns: `true` if and only if the elements `e` of `range` are partitioned
3325 // with respect to the expression `bool(invoke(pred, invoke(proj, e)))`.
3326 //
3327 // Complexity: Linear. At most `size(range)` applications of `pred` and `proj`.
3328 //
3329 // Reference: https://wg21.link/alg.partitions#:~:text=ranges::is_partitioned(R
3330 template <typename Range,
3331 typename Pred,
3332 typename Proj = std::identity,
3333 typename = internal::range_category_t<Range>>
3334 constexpr auto is_partitioned(Range&& range, Pred pred, Proj proj = {}) {
3335 return ranges::is_partitioned(ranges::begin(range), ranges::end(range),
3336 std::move(pred), std::move(proj));
3337 }
3338
3339 // Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
3340 //
3341 // Effects: Places all the elements `e` in `[first, last)` that satisfy `E(e)`
3342 // before all the elements that do not.
3343 //
3344 // Returns: Let `i` be an iterator such that `E(*j)` is `true` for every
3345 // iterator `j` in `[first, i)` and `false` for every iterator `j` in
3346 // `[i, last)`. Returns: i.
3347 //
3348 // Complexity: Let `N = last - first`:
3349 // Exactly `N` applications of the predicate and projection. At most `N / 2`
3350 // swaps if the type of `first` models `bidirectional_iterator`, and at most `N`
3351 // swaps otherwise.
3352 //
3353 // Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition(I
3354 template <typename ForwardIterator,
3355 typename Pred,
3356 typename Proj = std::identity,
3357 typename = internal::iterator_category_t<ForwardIterator>>
3358 constexpr auto partition(ForwardIterator first,
3359 ForwardIterator last,
3360 Pred pred,
3361 Proj proj = {}) {
3362 return std::partition(first, last,
3363 internal::ProjectedUnaryPredicate(pred, proj));
3364 }
3365
3366 // Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
3367 //
3368 // Effects: Places all the elements `e` in `range` that satisfy `E(e)` before
3369 // all the elements that do not.
3370 //
3371 // Returns: Let `i` be an iterator such that `E(*j)` is `true` for every
3372 // iterator `j` in `[begin(range), i)` and `false` for every iterator `j` in
3373 // `[i, last)`. Returns: i.
3374 //
3375 // Complexity: Let `N = size(range)`:
3376 // Exactly `N` applications of the predicate and projection. At most `N / 2`
3377 // swaps if the type of `first` models `bidirectional_iterator`, and at most `N`
3378 // swaps otherwise.
3379 //
3380 // Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition(R
3381 template <typename Range,
3382 typename Pred,
3383 typename Proj = std::identity,
3384 typename = internal::range_category_t<Range>>
3385 constexpr auto partition(Range&& range, Pred pred, Proj proj = {}) {
3386 return ranges::partition(ranges::begin(range), ranges::end(range),
3387 std::move(pred), std::move(proj));
3388 }
3389
3390 // Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
3391 //
3392 // Effects: Places all the elements `e` in `[first, last)` that satisfy `E(e)`
3393 // before all the elements that do not. The relative order of the elements in
3394 // both groups is preserved.
3395 //
3396 // Returns: Let `i` be an iterator such that for every iterator `j` in
3397 // `[first, i)`, `E(*j)` is `true`, and for every iterator `j` in the range
3398 // `[i, last)`, `E(*j)` is `false`. Returns: `i`.
3399 //
3400 // Complexity: Let `N = last - first`:
3401 // At most `N log N` swaps, but only `O(N)` swaps if there is enough extra
3402 // memory. Exactly `N` applications of the predicate and projection.
3403 //
3404 // Reference:
3405 // https://wg21.link/alg.partitions#:~:text=ranges::stable_partition(I
3406 template <typename BidirectionalIterator,
3407 typename Pred,
3408 typename Proj = std::identity,
3409 typename = internal::iterator_category_t<BidirectionalIterator>>
3410 constexpr auto stable_partition(BidirectionalIterator first,
3411 BidirectionalIterator last,
3412 Pred pred,
3413 Proj proj = {}) {
3414 return std::stable_partition(first, last,
3415 internal::ProjectedUnaryPredicate(pred, proj));
3416 }
3417
3418 // Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
3419 //
3420 // Effects: Places all the elements `e` in `range` that satisfy `E(e)` before
3421 // all the elements that do not. The relative order of the elements in both
3422 // groups is preserved.
3423 //
3424 // Returns: Let `i` be an iterator such that for every iterator `j` in
3425 // `[begin(range), i)`, `E(*j)` is `true`, and for every iterator `j` in the
3426 // range `[i, end(range))`, `E(*j)` is `false`. Returns: `i`.
3427 //
3428 // Complexity: Let `N = size(range)`:
3429 // At most `N log N` swaps, but only `O(N)` swaps if there is enough extra
3430 // memory. Exactly `N` applications of the predicate and projection.
3431 //
3432 // Reference:
3433 // https://wg21.link/alg.partitions#:~:text=ranges::stable_partition(R
3434 template <typename Range,
3435 typename Pred,
3436 typename Proj = std::identity,
3437 typename = internal::range_category_t<Range>>
3438 constexpr auto stable_partition(Range&& range, Pred pred, Proj proj = {}) {
3439 return ranges::stable_partition(ranges::begin(range), ranges::end(range),
3440 std::move(pred), std::move(proj));
3441 }
3442
3443 // Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
3444 //
3445 // Mandates: The expression `*first` is writable to `out_true` and `out_false`.
3446 //
3447 // Preconditions: The input range and output ranges do not overlap.
3448 //
3449 // Effects: For each iterator `i` in `[first, last)`, copies `*i` to the output
3450 // range beginning with `out_true` if `E(*i)` is `true`, or to the output range
3451 // beginning with `out_false` otherwise.
3452 //
3453 // Returns: Let `o1` be the end of the output range beginning at `out_true`, and
3454 // `o2` the end of the output range beginning at `out_false`.
3455 // Returns `{o1, o2}`.
3456 //
3457 // Complexity: Exactly `last - first` applications of `pred` and `proj`.
3458 //
3459 // Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition_copy(I
3460 template <typename InputIterator,
3461 typename OutputIterator1,
3462 typename OutputIterator2,
3463 typename Pred,
3464 typename Proj = std::identity,
3465 typename = internal::iterator_category_t<InputIterator>,
3466 typename = internal::iterator_category_t<OutputIterator1>,
3467 typename = internal::iterator_category_t<OutputIterator2>>
3468 constexpr auto partition_copy(InputIterator first,
3469 InputIterator last,
3470 OutputIterator1 out_true,
3471 OutputIterator2 out_false,
3472 Pred pred,
3473 Proj proj = {}) {
3474 return std::partition_copy(first, last, out_true, out_false,
3475 internal::ProjectedUnaryPredicate(pred, proj));
3476 }
3477
3478 // Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
3479 //
3480 // Mandates: The expression `*begin(range)` is writable to `out_true` and
3481 // `out_false`.
3482 //
3483 // Preconditions: The input range and output ranges do not overlap.
3484 //
3485 // Effects: For each iterator `i` in `range`, copies `*i` to the output range
3486 // beginning with `out_true` if `E(*i)` is `true`, or to the output range
3487 // beginning with `out_false` otherwise.
3488 //
3489 // Returns: Let `o1` be the end of the output range beginning at `out_true`, and
3490 // `o2` the end of the output range beginning at `out_false`.
3491 // Returns `{o1, o2}`.
3492 //
3493 // Complexity: Exactly `size(range)` applications of `pred` and `proj`.
3494 //
3495 // Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition_copy(R
3496 template <typename Range,
3497 typename OutputIterator1,
3498 typename OutputIterator2,
3499 typename Pred,
3500 typename Proj = std::identity,
3501 typename = internal::range_category_t<Range>,
3502 typename = internal::iterator_category_t<OutputIterator1>,
3503 typename = internal::iterator_category_t<OutputIterator2>>
3504 constexpr auto partition_copy(Range&& range,
3505 OutputIterator1 out_true,
3506 OutputIterator2 out_false,
3507 Pred pred,
3508 Proj proj = {}) {
3509 return ranges::partition_copy(ranges::begin(range), ranges::end(range),
3510 out_true, out_false, std::move(pred),
3511 std::move(proj));
3512 }
3513
3514 // let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
3515 //
3516 // Preconditions: The elements `e` of `[first, last)` are partitioned with
3517 // respect to `E(e)`.
3518 //
3519 // Returns: An iterator `mid` such that `E(*i)` is `true` for all iterators `i`
3520 // in `[first, mid)`, and `false` for all iterators `i` in `[mid, last)`.
3521 //
3522 // Complexity: `O(log(last - first))` applications of `pred` and `proj`.
3523 //
3524 // Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition_point(I
3525 template <typename ForwardIterator,
3526 typename Pred,
3527 typename Proj = std::identity,
3528 typename = internal::iterator_category_t<ForwardIterator>>
3529 constexpr auto partition_point(ForwardIterator first,
3530 ForwardIterator last,
3531 Pred pred,
3532 Proj proj = {}) {
3533 return std::partition_point(first, last,
3534 internal::ProjectedUnaryPredicate(pred, proj));
3535 }
3536
3537 // let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
3538 //
3539 // Preconditions: The elements `e` of `range` are partitioned with respect to
3540 // `E(e)`.
3541 //
3542 // Returns: An iterator `mid` such that `E(*i)` is `true` for all iterators `i`
3543 // in `[begin(range), mid)`, and `false` for all iterators `i` in
3544 // `[mid, end(range))`.
3545 //
3546 // Complexity: `O(log(size(range)))` applications of `pred` and `proj`.
3547 //
3548 // Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition_point(R
3549 template <typename Range,
3550 typename Pred,
3551 typename Proj = std::identity,
3552 typename = internal::range_category_t<Range>>
3553 constexpr auto partition_point(Range&& range, Pred pred, Proj proj = {}) {
3554 return ranges::partition_point(ranges::begin(range), ranges::end(range),
3555 std::move(pred), std::move(proj));
3556 }
3557
3558 // [alg.merge] Merge
3559 // Reference: https://wg21.link/alg.merge
3560
3561 // Let `N` be `(last1 - first1) + (last2 - first2)`.
3562 //
3563 // Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
3564 // with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
3565 // range does not overlap with either of the original ranges.
3566 //
3567 // Effects: Copies all the elements of the two ranges `[first1, last1)` and
3568 // `[first2, last2)` into the range `[result, result_last)`, where `result_last`
3569 // is `result + N`. If an element `a` precedes `b` in an input range, `a` is
3570 // copied into the output range before `b`. If `e1` is an element of
3571 // `[first1, last1)` and `e2` of `[first2, last2)`, `e2` is copied into the
3572 // output range before `e1` if and only if
3573 // `bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))` is `true`.
3574 //
3575 // Returns: `result_last`.
3576 //
3577 // Complexity: At most `N - 1` comparisons and applications of each projection.
3578 //
3579 // Remarks: Stable.
3580 //
3581 // Reference: https://wg21.link/alg.merge#:~:text=ranges::merge(I1
3582 template <typename InputIterator1,
3583 typename InputIterator2,
3584 typename OutputIterator,
3585 typename Comp = ranges::less,
3586 typename Proj1 = std::identity,
3587 typename Proj2 = std::identity,
3588 typename = internal::iterator_category_t<InputIterator1>,
3589 typename = internal::iterator_category_t<InputIterator2>,
3590 typename = internal::iterator_category_t<OutputIterator>,
3591 typename = indirect_result_t<Comp&,
3592 projected<InputIterator1, Proj1>,
3593 projected<InputIterator2, Proj2>>,
3594 typename = indirect_result_t<Comp&,
3595 projected<InputIterator2, Proj2>,
3596 projected<InputIterator1, Proj1>>>
3597 constexpr auto merge(InputIterator1 first1,
3598 InputIterator1 last1,
3599 InputIterator2 first2,
3600 InputIterator2 last2,
3601 OutputIterator result,
3602 Comp comp = {},
3603 Proj1 proj1 = {},
3604 Proj2 proj2 = {}) {
3605 // Needs to opt-in to all permutations, since std::merge expects
3606 // comp(proj2(lhs), proj1(rhs)) to compile.
3607 return std::merge(
3608 first1, last1, first2, last2, result,
3609 internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
3610 }
3611
3612 // Let `N` be `size(range1) + size(range2)`.
3613 //
3614 // Preconditions: The ranges `range1` and `range2` are sorted with respect to
3615 // `comp` and `proj1` or `proj2`, respectively. The resulting range does not
3616 // overlap with either of the original ranges.
3617 //
3618 // Effects: Copies all the elements of the two ranges `range1` and `range2` into
3619 // the range `[result, result_last)`, where `result_last` is `result + N`. If an
3620 // element `a` precedes `b` in an input range, `a` is copied into the output
3621 // range before `b`. If `e1` is an element of `range1` and `e2` of `range2`,
3622 // `e2` is copied into the output range before `e1` if and only if
3623 // `bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))` is `true`.
3624 //
3625 // Returns: `result_last`.
3626 //
3627 // Complexity: At most `N - 1` comparisons and applications of each projection.
3628 //
3629 // Remarks: Stable.
3630 //
3631 // Reference: https://wg21.link/alg.merge#:~:text=ranges::merge(R1
3632 template <typename Range1,
3633 typename Range2,
3634 typename OutputIterator,
3635 typename Comp = ranges::less,
3636 typename Proj1 = std::identity,
3637 typename Proj2 = std::identity,
3638 typename = internal::range_category_t<Range1>,
3639 typename = internal::range_category_t<Range2>,
3640 typename = internal::iterator_category_t<OutputIterator>,
3641 typename = indirect_result_t<Comp&,
3642 projected<iterator_t<Range1>, Proj1>,
3643 projected<iterator_t<Range2>, Proj2>>,
3644 typename = indirect_result_t<Comp&,
3645 projected<iterator_t<Range2>, Proj2>,
3646 projected<iterator_t<Range1>, Proj1>>>
3647 constexpr auto merge(Range1&& range1,
3648 Range2&& range2,
3649 OutputIterator result,
3650 Comp comp = {},
3651 Proj1 proj1 = {},
3652 Proj2 proj2 = {}) {
3653 return ranges::merge(ranges::begin(range1), ranges::end(range1),
3654 ranges::begin(range2), ranges::end(range2), result,
3655 std::move(comp), std::move(proj1), std::move(proj2));
3656 }
3657
3658 // Preconditions: `[first, middle)` and `[middle, last)` are valid ranges sorted
3659 // with respect to `comp` and `proj`.
3660 //
3661 // Effects: Merges two sorted consecutive ranges `[first, middle)` and
3662 // `[middle, last)`, putting the result of the merge into the range
3663 // `[first, last)`. The resulting range is sorted with respect to `comp` and
3664 // `proj`.
3665 //
3666 // Returns: `last`.
3667 //
3668 // Complexity: Let `N = last - first`: If enough additional memory is available,
3669 // exactly `N - 1` comparisons. Otherwise, `O(N log N)` comparisons. In either
3670 // case, twice as many projections as comparisons.
3671 //
3672 // Remarks: Stable.
3673 //
3674 // Reference: https://wg21.link/alg.merge#:~:text=ranges::inplace_merge(I
3675 template <typename BidirectionalIterator,
3676 typename Comp = ranges::less,
3677 typename Proj = std::identity,
3678 typename = internal::iterator_category_t<BidirectionalIterator>>
3679 constexpr auto inplace_merge(BidirectionalIterator first,
3680 BidirectionalIterator middle,
3681 BidirectionalIterator last,
3682 Comp comp = {},
3683 Proj proj = {}) {
3684 std::inplace_merge(first, middle, last,
3685 internal::ProjectedBinaryPredicate(comp, proj, proj));
3686 return last;
3687 }
3688
3689 // Preconditions: `[begin(range), middle)` and `[middle, end(range))` are valid
3690 // ranges sorted with respect to `comp` and `proj`.
3691 //
3692 // Effects: Merges two sorted consecutive ranges `[begin(range), middle)` and
3693 // `[middle, end(range))`, putting the result of the merge into `range`. The
3694 // resulting range is sorted with respect to `comp` and `proj`.
3695 //
3696 // Returns: `end(range)`.
3697 //
3698 // Complexity: Let `N = size(range)`: If enough additional memory is available,
3699 // exactly `N - 1` comparisons. Otherwise, `O(N log N)` comparisons. In either
3700 // case, twice as many projections as comparisons.
3701 //
3702 // Remarks: Stable.
3703 //
3704 // Reference: https://wg21.link/alg.merge#:~:text=ranges::inplace_merge(R
3705 template <typename Range,
3706 typename Comp = ranges::less,
3707 typename Proj = std::identity,
3708 typename = internal::range_category_t<Range>>
3709 constexpr auto inplace_merge(Range&& range,
3710 iterator_t<Range> middle,
3711 Comp comp = {},
3712 Proj proj = {}) {
3713 return ranges::inplace_merge(ranges::begin(range), middle, ranges::end(range),
3714 std::move(comp), std::move(proj));
3715 }
3716
3717 // [alg.set.operations] Set operations on sorted structures
3718 // Reference: https://wg21.link/alg.set.operations
3719
3720 // [includes] includes
3721 // Reference: https://wg21.link/includes
3722
3723 // Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
3724 // with respect to `comp` and `proj1` or `proj2`, respectively.
3725 //
3726 // Returns: `true` if and only if `[first2, last2)` is a subsequence of
3727 // `[first1, last1)`.
3728 //
3729 // Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
3730 // comparisons and applications of each projection.
3731 //
3732 // Reference: https://wg21.link/includes#:~:text=ranges::includes(I1
3733 template <typename InputIterator1,
3734 typename InputIterator2,
3735 typename Comp = ranges::less,
3736 typename Proj1 = std::identity,
3737 typename Proj2 = std::identity,
3738 typename = internal::iterator_category_t<InputIterator1>,
3739 typename = internal::iterator_category_t<InputIterator2>,
3740 typename = indirect_result_t<Comp&,
3741 projected<InputIterator1, Proj1>,
3742 projected<InputIterator2, Proj2>>,
3743 typename = indirect_result_t<Comp&,
3744 projected<InputIterator2, Proj2>,
3745 projected<InputIterator1, Proj1>>>
3746 constexpr auto includes(InputIterator1 first1,
3747 InputIterator1 last1,
3748 InputIterator2 first2,
3749 InputIterator2 last2,
3750 Comp comp = {},
3751 Proj1 proj1 = {},
3752 Proj2 proj2 = {}) {
3753 DCHECK(ranges::is_sorted(first1, last1, comp, proj1));
3754 DCHECK(ranges::is_sorted(first2, last2, comp, proj2));
3755 // Needs to opt-in to all permutations, since std::includes expects
3756 // comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to compile.
3757 return std::includes(
3758 first1, last1, first2, last2,
3759 internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
3760 }
3761
3762 // Preconditions: The ranges `range1` and `range2` are sorted with respect to
3763 // `comp` and `proj1` or `proj2`, respectively.
3764 //
3765 // Returns: `true` if and only if `range2` is a subsequence of `range1`.
3766 //
3767 // Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
3768 // applications of each projection.
3769 //
3770 // Reference: https://wg21.link/includes#:~:text=ranges::includes(R1
3771 template <typename Range1,
3772 typename Range2,
3773 typename Comp = ranges::less,
3774 typename Proj1 = std::identity,
3775 typename Proj2 = std::identity,
3776 typename = internal::range_category_t<Range1>,
3777 typename = internal::range_category_t<Range2>,
3778 typename = indirect_result_t<Comp&,
3779 projected<iterator_t<Range1>, Proj1>,
3780 projected<iterator_t<Range2>, Proj2>>,
3781 typename = indirect_result_t<Comp&,
3782 projected<iterator_t<Range2>, Proj2>,
3783 projected<iterator_t<Range1>, Proj1>>>
3784 constexpr auto includes(Range1&& range1,
3785 Range2&& range2,
3786 Comp comp = {},
3787 Proj1 proj1 = {},
3788 Proj2 proj2 = {}) {
3789 return ranges::includes(ranges::begin(range1), ranges::end(range1),
3790 ranges::begin(range2), ranges::end(range2),
3791 std::move(comp), std::move(proj1), std::move(proj2));
3792 }
3793
3794 // [set.union] set_union
3795 // Reference: https://wg21.link/set.union
3796
3797 // Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
3798 // with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
3799 // range does not overlap with either of the original ranges.
3800 //
3801 // Effects: Constructs a sorted union of the elements from the two ranges; that
3802 // is, the set of elements that are present in one or both of the ranges.
3803 //
3804 // Returns: The end of the constructed range.
3805 //
3806 // Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
3807 // comparisons and applications of each projection.
3808 //
3809 // Remarks: Stable. If `[first1, last1)` contains `m` elements that are
3810 // equivalent to each other and `[first2, last2)` contains `n` elements that are
3811 // equivalent to them, then all `m` elements from the first range are copied to
3812 // the output range, in order, and then the final `max(n - m , 0)` elements from
3813 // the second range are copied to the output range, in order.
3814 //
3815 // Reference: https://wg21.link/set.union#:~:text=ranges::set_union(I1
3816 template <typename InputIterator1,
3817 typename InputIterator2,
3818 typename OutputIterator,
3819 typename Comp = ranges::less,
3820 typename Proj1 = std::identity,
3821 typename Proj2 = std::identity,
3822 typename = internal::iterator_category_t<InputIterator1>,
3823 typename = internal::iterator_category_t<InputIterator2>,
3824 typename = internal::iterator_category_t<OutputIterator>,
3825 typename = indirect_result_t<Comp&,
3826 projected<InputIterator1, Proj1>,
3827 projected<InputIterator2, Proj2>>,
3828 typename = indirect_result_t<Comp&,
3829 projected<InputIterator2, Proj2>,
3830 projected<InputIterator1, Proj1>>>
3831 constexpr auto set_union(InputIterator1 first1,
3832 InputIterator1 last1,
3833 InputIterator2 first2,
3834 InputIterator2 last2,
3835 OutputIterator result,
3836 Comp comp = {},
3837 Proj1 proj1 = {},
3838 Proj2 proj2 = {}) {
3839 // Needs to opt-in to all permutations, since std::set_union expects
3840 // comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to compile.
3841 return std::set_union(
3842 first1, last1, first2, last2, result,
3843 internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
3844 }
3845
3846 // Preconditions: The ranges `range1` and `range2` are sorted with respect to
3847 // `comp` and `proj1` or `proj2`, respectively. The resulting range does not
3848 // overlap with either of the original ranges.
3849 //
3850 // Effects: Constructs a sorted union of the elements from the two ranges; that
3851 // is, the set of elements that are present in one or both of the ranges.
3852 //
3853 // Returns: The end of the constructed range.
3854 //
3855 // Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
3856 // applications of each projection.
3857 //
3858 // Remarks: Stable. If `range1` contains `m` elements that are equivalent to
3859 // each other and `range2` contains `n` elements that are equivalent to them,
3860 // then all `m` elements from the first range are copied to the output range, in
3861 // order, and then the final `max(n - m , 0)` elements from the second range are
3862 // copied to the output range, in order.
3863 //
3864 // Reference: https://wg21.link/set.union#:~:text=ranges::set_union(R1
3865 template <typename Range1,
3866 typename Range2,
3867 typename OutputIterator,
3868 typename Comp = ranges::less,
3869 typename Proj1 = std::identity,
3870 typename Proj2 = std::identity,
3871 typename = internal::range_category_t<Range1>,
3872 typename = internal::range_category_t<Range2>,
3873 typename = internal::iterator_category_t<OutputIterator>,
3874 typename = indirect_result_t<Comp&,
3875 projected<iterator_t<Range1>, Proj1>,
3876 projected<iterator_t<Range2>, Proj2>>,
3877 typename = indirect_result_t<Comp&,
3878 projected<iterator_t<Range2>, Proj2>,
3879 projected<iterator_t<Range1>, Proj1>>>
3880 constexpr auto set_union(Range1&& range1,
3881 Range2&& range2,
3882 OutputIterator result,
3883 Comp comp = {},
3884 Proj1 proj1 = {},
3885 Proj2 proj2 = {}) {
3886 return ranges::set_union(ranges::begin(range1), ranges::end(range1),
3887 ranges::begin(range2), ranges::end(range2), result,
3888 std::move(comp), std::move(proj1), std::move(proj2));
3889 }
3890
3891 // [set.intersection] set_intersection
3892 // Reference: https://wg21.link/set.intersection
3893
3894 // Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
3895 // with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
3896 // range does not overlap with either of the original ranges.
3897 //
3898 // Effects: Constructs a sorted intersection of the elements from the two
3899 // ranges; that is, the set of elements that are present in both of the ranges.
3900 //
3901 // Returns: The end of the constructed range.
3902 //
3903 // Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
3904 // comparisons and applications of each projection.
3905 //
3906 // Remarks: Stable. If `[first1, last1)` contains `m` elements that are
3907 // equivalent to each other and `[first2, last2)` contains `n` elements that are
3908 // equivalent to them, the first `min(m, n)` elements are copied from the first
3909 // range to the output range, in order.
3910 //
3911 // Reference:
3912 // https://wg21.link/set.intersection#:~:text=ranges::set_intersection(I1
3913 template <typename InputIterator1,
3914 typename InputIterator2,
3915 typename OutputIterator,
3916 typename Comp = ranges::less,
3917 typename Proj1 = std::identity,
3918 typename Proj2 = std::identity,
3919 typename = internal::iterator_category_t<InputIterator1>,
3920 typename = internal::iterator_category_t<InputIterator2>,
3921 typename = internal::iterator_category_t<OutputIterator>,
3922 typename = indirect_result_t<Comp&,
3923 projected<InputIterator1, Proj1>,
3924 projected<InputIterator2, Proj2>>,
3925 typename = indirect_result_t<Comp&,
3926 projected<InputIterator2, Proj2>,
3927 projected<InputIterator1, Proj1>>>
3928 constexpr auto set_intersection(InputIterator1 first1,
3929 InputIterator1 last1,
3930 InputIterator2 first2,
3931 InputIterator2 last2,
3932 OutputIterator result,
3933 Comp comp = {},
3934 Proj1 proj1 = {},
3935 Proj2 proj2 = {}) {
3936 // Needs to opt-in to all permutations, since std::set_intersection expects
3937 // comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to compile.
3938 return std::set_intersection(
3939 first1, last1, first2, last2, result,
3940 internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
3941 }
3942
3943 // Preconditions: The ranges `range1` and `range2` are sorted with respect to
3944 // `comp` and `proj1` or `proj2`, respectively. The resulting range does not
3945 // overlap with either of the original ranges.
3946 //
3947 // Effects: Constructs a sorted intersection of the elements from the two
3948 // ranges; that is, the set of elements that are present in both of the ranges.
3949 //
3950 // Returns: The end of the constructed range.
3951 //
3952 // Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
3953 // applications of each projection.
3954 //
3955 // Remarks: Stable. If `range1` contains `m` elements that are equivalent to
3956 // each other and `range2` contains `n` elements that are equivalent to them,
3957 // the first `min(m, n)` elements are copied from the first range to the output
3958 // range, in order.
3959 //
3960 // Reference:
3961 // https://wg21.link/set.intersection#:~:text=ranges::set_intersection(R1
3962 template <typename Range1,
3963 typename Range2,
3964 typename OutputIterator,
3965 typename Comp = ranges::less,
3966 typename Proj1 = std::identity,
3967 typename Proj2 = std::identity,
3968 typename = internal::range_category_t<Range1>,
3969 typename = internal::range_category_t<Range2>,
3970 typename = internal::iterator_category_t<OutputIterator>,
3971 typename = indirect_result_t<Comp&,
3972 projected<iterator_t<Range1>, Proj1>,
3973 projected<iterator_t<Range2>, Proj2>>,
3974 typename = indirect_result_t<Comp&,
3975 projected<iterator_t<Range2>, Proj2>,
3976 projected<iterator_t<Range1>, Proj1>>>
3977 constexpr auto set_intersection(Range1&& range1,
3978 Range2&& range2,
3979 OutputIterator result,
3980 Comp comp = {},
3981 Proj1 proj1 = {},
3982 Proj2 proj2 = {}) {
3983 return ranges::set_intersection(ranges::begin(range1), ranges::end(range1),
3984 ranges::begin(range2), ranges::end(range2),
3985 result, std::move(comp), std::move(proj1),
3986 std::move(proj2));
3987 }
3988
3989 // [set.difference] set_difference
3990 // Reference: https://wg21.link/set.difference
3991
3992 // Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
3993 // with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
3994 // range does not overlap with either of the original ranges.
3995 //
3996 // Effects: Copies the elements of the range `[first1, last1)` which are not
3997 // present in the range `[first2, last2)` to the range beginning at `result`.
3998 // The elements in the constructed range are sorted.
3999 //
4000 // Returns: The end of the constructed range.
4001 //
4002 // Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
4003 // comparisons and applications of each projection.
4004 //
4005 // Remarks: If `[first1, last1)` contains `m` elements that are equivalent to
4006 // each other and `[first2, last2)` contains `n` elements that are equivalent to
4007 // them, the last `max(m - n, 0)` elements from `[first1, last1)` are copied to
4008 // the output range, in order.
4009 //
4010 // Reference:
4011 // https://wg21.link/set.difference#:~:text=ranges::set_difference(I1
4012 template <typename InputIterator1,
4013 typename InputIterator2,
4014 typename OutputIterator,
4015 typename Comp = ranges::less,
4016 typename Proj1 = std::identity,
4017 typename Proj2 = std::identity,
4018 typename = internal::iterator_category_t<InputIterator1>,
4019 typename = internal::iterator_category_t<InputIterator2>,
4020 typename = internal::iterator_category_t<OutputIterator>,
4021 typename = indirect_result_t<Comp&,
4022 projected<InputIterator1, Proj1>,
4023 projected<InputIterator2, Proj2>>,
4024 typename = indirect_result_t<Comp&,
4025 projected<InputIterator2, Proj2>,
4026 projected<InputIterator1, Proj1>>>
4027 constexpr auto set_difference(InputIterator1 first1,
4028 InputIterator1 last1,
4029 InputIterator2 first2,
4030 InputIterator2 last2,
4031 OutputIterator result,
4032 Comp comp = {},
4033 Proj1 proj1 = {},
4034 Proj2 proj2 = {}) {
4035 // Needs to opt-in to all permutations, since std::set_difference expects
4036 // comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to compile.
4037 return std::set_difference(
4038 first1, last1, first2, last2, result,
4039 internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
4040 }
4041
4042 // Preconditions: The ranges `range1` and `range2` are sorted with respect to
4043 // `comp` and `proj1` or `proj2`, respectively. The resulting range does not
4044 // overlap with either of the original ranges.
4045 //
4046 // Effects: Copies the elements of `range1` which are not present in `range2`
4047 // to the range beginning at `result`. The elements in the constructed range are
4048 // sorted.
4049 //
4050 // Returns: The end of the constructed range.
4051 //
4052 // Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
4053 // applications of each projection.
4054 //
4055 // Remarks: Stable. If `range1` contains `m` elements that are equivalent to
4056 // each other and `range2` contains `n` elements that are equivalent to them,
4057 // the last `max(m - n, 0)` elements from `range1` are copied to the output
4058 // range, in order.
4059 //
4060 // Reference:
4061 // https://wg21.link/set.difference#:~:text=ranges::set_difference(R1
4062 template <typename Range1,
4063 typename Range2,
4064 typename OutputIterator,
4065 typename Comp = ranges::less,
4066 typename Proj1 = std::identity,
4067 typename Proj2 = std::identity,
4068 typename = internal::range_category_t<Range1>,
4069 typename = internal::range_category_t<Range2>,
4070 typename = internal::iterator_category_t<OutputIterator>,
4071 typename = indirect_result_t<Comp&,
4072 projected<iterator_t<Range1>, Proj1>,
4073 projected<iterator_t<Range2>, Proj2>>,
4074 typename = indirect_result_t<Comp&,
4075 projected<iterator_t<Range2>, Proj2>,
4076 projected<iterator_t<Range1>, Proj1>>>
4077 constexpr auto set_difference(Range1&& range1,
4078 Range2&& range2,
4079 OutputIterator result,
4080 Comp comp = {},
4081 Proj1 proj1 = {},
4082 Proj2 proj2 = {}) {
4083 return ranges::set_difference(ranges::begin(range1), ranges::end(range1),
4084 ranges::begin(range2), ranges::end(range2),
4085 result, std::move(comp), std::move(proj1),
4086 std::move(proj2));
4087 }
4088
4089 // [set.symmetric.difference] set_symmetric_difference
4090 // Reference: https://wg21.link/set.symmetric.difference
4091
4092 // Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
4093 // with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
4094 // range does not overlap with either of the original ranges.
4095 //
4096 // Effects: Copies the elements of the range `[first1, last1)` that are not
4097 // present in the range `[first2, last2)`, and the elements of the range
4098 // `[first2, last2)` that are not present in the range `[first1, last1)` to the
4099 // range beginning at `result`. The elements in the constructed range are
4100 // sorted.
4101 //
4102 // Returns: The end of the constructed range.
4103 //
4104 // Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
4105 // comparisons and applications of each projection.
4106 //
4107 // Remarks: Stable. If `[first1, last1)` contains `m` elements that are
4108 // equivalent to each other and `[first2, last2)` contains `n` elements that are
4109 // equivalent to them, then `|m - n|` of those elements shall be copied to the
4110 // output range: the last `m - n` of these elements from `[first1, last1)` if
4111 // `m > n`, and the last `n - m` of these elements from `[first2, last2)` if
4112 // `m < n`. In either case, the elements are copied in order.
4113 //
4114 // Reference:
4115 // https://wg21.link/set.symmetric.difference#:~:text=set_symmetric_difference(I1
4116 template <typename InputIterator1,
4117 typename InputIterator2,
4118 typename OutputIterator,
4119 typename Comp = ranges::less,
4120 typename Proj1 = std::identity,
4121 typename Proj2 = std::identity,
4122 typename = internal::iterator_category_t<InputIterator1>,
4123 typename = internal::iterator_category_t<InputIterator2>,
4124 typename = internal::iterator_category_t<OutputIterator>,
4125 typename = indirect_result_t<Comp&,
4126 projected<InputIterator1, Proj1>,
4127 projected<InputIterator2, Proj2>>,
4128 typename = indirect_result_t<Comp&,
4129 projected<InputIterator2, Proj2>,
4130 projected<InputIterator1, Proj1>>>
4131 constexpr auto set_symmetric_difference(InputIterator1 first1,
4132 InputIterator1 last1,
4133 InputIterator2 first2,
4134 InputIterator2 last2,
4135 OutputIterator result,
4136 Comp comp = {},
4137 Proj1 proj1 = {},
4138 Proj2 proj2 = {}) {
4139 // Needs to opt-in to all permutations, since std::set_symmetric_difference
4140 // expects comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to
4141 // compile.
4142 return std::set_symmetric_difference(
4143 first1, last1, first2, last2, result,
4144 internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
4145 }
4146
4147 // Preconditions: The ranges `range1` and `range2` are sorted with respect to
4148 // `comp` and `proj1` or `proj2`, respectively. The resulting range does not
4149 // overlap with either of the original ranges.
4150 //
4151 // Effects: Copies the elements of `range1` that are not present in `range2`,
4152 // and the elements of `range2` that are not present in `range1` to the range
4153 // beginning at `result`. The elements in the constructed range are sorted.
4154 //
4155 // Returns: The end of the constructed range.
4156 //
4157 // Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
4158 // applications of each projection.
4159 //
4160 // Remarks: Stable. If `range1` contains `m` elements that are equivalent to
4161 // each other and `range2` contains `n` elements that are equivalent to them,
4162 // then `|m - n|` of those elements shall be copied to the output range: the
4163 // last `m - n` of these elements from `range1` if `m > n`, and the last `n - m`
4164 // of these elements from `range2` if `m < n`. In either case, the elements are
4165 // copied in order.
4166 //
4167 // Reference:
4168 // https://wg21.link/set.symmetric.difference#:~:text=set_symmetric_difference(R1
4169 template <typename Range1,
4170 typename Range2,
4171 typename OutputIterator,
4172 typename Comp = ranges::less,
4173 typename Proj1 = std::identity,
4174 typename Proj2 = std::identity,
4175 typename = internal::range_category_t<Range1>,
4176 typename = internal::range_category_t<Range2>,
4177 typename = internal::iterator_category_t<OutputIterator>,
4178 typename = indirect_result_t<Comp&,
4179 projected<iterator_t<Range1>, Proj1>,
4180 projected<iterator_t<Range2>, Proj2>>,
4181 typename = indirect_result_t<Comp&,
4182 projected<iterator_t<Range2>, Proj2>,
4183 projected<iterator_t<Range1>, Proj1>>>
4184 constexpr auto set_symmetric_difference(Range1&& range1,
4185 Range2&& range2,
4186 OutputIterator result,
4187 Comp comp = {},
4188 Proj1 proj1 = {},
4189 Proj2 proj2 = {}) {
4190 return ranges::set_symmetric_difference(
4191 ranges::begin(range1), ranges::end(range1), ranges::begin(range2),
4192 ranges::end(range2), result, std::move(comp), std::move(proj1),
4193 std::move(proj2));
4194 }
4195
4196 // [alg.heap.operations] Heap operations
4197 // Reference: https://wg21.link/alg.heap.operations
4198
4199 // [push.heap] push_heap
4200 // Reference: https://wg21.link/push.heap
4201
4202 // Preconditions: The range `[first, last - 1)` is a valid heap with respect to
4203 // `comp` and `proj`.
4204 //
4205 // Effects: Places the value in the location `last - 1` into the resulting heap
4206 // `[first, last)`.
4207 //
4208 // Returns: `last`.
4209 //
4210 // Complexity: At most `log(last - first)` comparisons and twice as many
4211 // projections.
4212 //
4213 // Reference: https://wg21.link/push.heap#:~:text=ranges::push_heap(I
4214 template <typename RandomAccessIterator,
4215 typename Comp = ranges::less,
4216 typename Proj = std::identity,
4217 typename = internal::iterator_category_t<RandomAccessIterator>,
4218 typename = indirect_result_t<Comp&,
4219 projected<RandomAccessIterator, Proj>,
4220 projected<RandomAccessIterator, Proj>>>
4221 constexpr auto push_heap(RandomAccessIterator first,
4222 RandomAccessIterator last,
4223 Comp comp = {},
4224 Proj proj = {}) {
4225 std::push_heap(first, last,
4226 internal::ProjectedBinaryPredicate(comp, proj, proj));
4227 return last;
4228 }
4229
4230 // Preconditions: The range `[begin(range), end(range) - 1)` is a valid heap
4231 // with respect to `comp` and `proj`.
4232 //
4233 // Effects: Places the value in the location `end(range) - 1` into the resulting
4234 // heap `range`.
4235 //
4236 // Returns: `end(range)`.
4237 //
4238 // Complexity: At most `log(size(range))` comparisons and twice as many
4239 // projections.
4240 //
4241 // Reference: https://wg21.link/push.heap#:~:text=ranges::push_heap(R
4242 template <typename Range,
4243 typename Comp = ranges::less,
4244 typename Proj = std::identity,
4245 typename = internal::range_category_t<Range>,
4246 typename = indirect_result_t<Comp&,
4247 projected<iterator_t<Range>, Proj>,
4248 projected<iterator_t<Range>, Proj>>>
4249 constexpr auto push_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
4250 return ranges::push_heap(ranges::begin(range), ranges::end(range),
4251 std::move(comp), std::move(proj));
4252 }
4253
4254 // [pop.heap] pop_heap
4255 // Reference: https://wg21.link/pop.heap
4256
4257 // Preconditions: The range `[first, last)` is a valid non-empty heap with
4258 // respect to `comp` and `proj`.
4259 //
4260 // Effects: Swaps the value in the location `first` with the value in the
4261 // location `last - 1` and makes `[first, last - 1)` into a heap with respect to
4262 // `comp` and `proj`.
4263 //
4264 // Returns: `last`.
4265 //
4266 // Complexity: At most `2 log(last - first)` comparisons and twice as many
4267 // projections.
4268 //
4269 // Reference: https://wg21.link/pop.heap#:~:text=ranges::pop_heap(I
4270 template <typename RandomAccessIterator,
4271 typename Comp = ranges::less,
4272 typename Proj = std::identity,
4273 typename = internal::iterator_category_t<RandomAccessIterator>,
4274 typename = indirect_result_t<Comp&,
4275 projected<RandomAccessIterator, Proj>,
4276 projected<RandomAccessIterator, Proj>>>
4277 constexpr auto pop_heap(RandomAccessIterator first,
4278 RandomAccessIterator last,
4279 Comp comp = {},
4280 Proj proj = {}) {
4281 std::pop_heap(first, last,
4282 internal::ProjectedBinaryPredicate(comp, proj, proj));
4283 return last;
4284 }
4285
4286 // Preconditions: `range` is a valid non-empty heap with respect to `comp` and
4287 // `proj`.
4288 //
4289 // Effects: Swaps the value in the location `begin(range)` with the value in the
4290 // location `end(range) - 1` and makes `[begin(range), end(range) - 1)` into a
4291 // heap with respect to `comp` and `proj`.
4292 //
4293 // Returns: `end(range)`.
4294 //
4295 // Complexity: At most `2 log(size(range))` comparisons and twice as many
4296 // projections.
4297 //
4298 // Reference: https://wg21.link/pop.heap#:~:text=ranges::pop_heap(R
4299 template <typename Range,
4300 typename Comp = ranges::less,
4301 typename Proj = std::identity,
4302 typename = internal::range_category_t<Range>,
4303 typename = indirect_result_t<Comp&,
4304 projected<iterator_t<Range>, Proj>,
4305 projected<iterator_t<Range>, Proj>>>
4306 constexpr auto pop_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
4307 return ranges::pop_heap(ranges::begin(range), ranges::end(range),
4308 std::move(comp), std::move(proj));
4309 }
4310
4311 // [make.heap] make_heap
4312 // Reference: https://wg21.link/make.heap
4313
4314 // Effects: Constructs a heap with respect to `comp` and `proj` out of the range
4315 // `[first, last)`.
4316 //
4317 // Returns: `last`.
4318 //
4319 // Complexity: At most `3 * (last - first)` comparisons and twice as many
4320 // projections.
4321 //
4322 // Reference: https://wg21.link/make.heap#:~:text=ranges::make_heap(I
4323 template <typename RandomAccessIterator,
4324 typename Comp = ranges::less,
4325 typename Proj = std::identity,
4326 typename = internal::iterator_category_t<RandomAccessIterator>,
4327 typename = indirect_result_t<Comp&,
4328 projected<RandomAccessIterator, Proj>,
4329 projected<RandomAccessIterator, Proj>>>
4330 constexpr auto make_heap(RandomAccessIterator first,
4331 RandomAccessIterator last,
4332 Comp comp = {},
4333 Proj proj = {}) {
4334 std::make_heap(first, last,
4335 internal::ProjectedBinaryPredicate(comp, proj, proj));
4336 return last;
4337 }
4338
4339 // Effects: Constructs a heap with respect to `comp` and `proj` out of `range`.
4340 //
4341 // Returns: `end(range)`.
4342 //
4343 // Complexity: At most `3 * size(range)` comparisons and twice as many
4344 // projections.
4345 //
4346 // Reference: https://wg21.link/make.heap#:~:text=ranges::make_heap(R
4347 template <typename Range,
4348 typename Comp = ranges::less,
4349 typename Proj = std::identity,
4350 typename = internal::range_category_t<Range>,
4351 typename = indirect_result_t<Comp&,
4352 projected<iterator_t<Range>, Proj>,
4353 projected<iterator_t<Range>, Proj>>>
4354 constexpr auto make_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
4355 return ranges::make_heap(ranges::begin(range), ranges::end(range),
4356 std::move(comp), std::move(proj));
4357 }
4358
4359 // [sort.heap] sort_heap
4360 // Reference: https://wg21.link/sort.heap
4361
4362 // Preconditions: The range `[first, last)` is a valid heap with respect to
4363 // `comp` and `proj`.
4364 //
4365 // Effects: Sorts elements in the heap `[first, last)` with respect to `comp`
4366 // and `proj`.
4367 //
4368 // Returns: `last`.
4369 //
4370 // Complexity: At most `2 N log N` comparisons, where `N = last - first`, and
4371 // twice as many projections.
4372 //
4373 // Reference: https://wg21.link/sort.heap#:~:text=ranges::sort_heap(I
4374 template <typename RandomAccessIterator,
4375 typename Comp = ranges::less,
4376 typename Proj = std::identity,
4377 typename = internal::iterator_category_t<RandomAccessIterator>,
4378 typename = indirect_result_t<Comp&,
4379 projected<RandomAccessIterator, Proj>,
4380 projected<RandomAccessIterator, Proj>>>
4381 constexpr auto sort_heap(RandomAccessIterator first,
4382 RandomAccessIterator last,
4383 Comp comp = {},
4384 Proj proj = {}) {
4385 std::sort_heap(first, last,
4386 internal::ProjectedBinaryPredicate(comp, proj, proj));
4387 return last;
4388 }
4389
4390 // Preconditions: `range` is a valid heap with respect to `comp` and `proj`.
4391 //
4392 // Effects: Sorts elements in the heap `range` with respect to `comp` and
4393 // `proj`.
4394 //
4395 // Returns: `end(range)`.
4396 //
4397 // Complexity: At most `2 N log N` comparisons, where `N = size(range)`, and
4398 // twice as many projections.
4399 //
4400 // Reference: https://wg21.link/sort.heap#:~:text=ranges::sort_heap(R
4401 template <typename Range,
4402 typename Comp = ranges::less,
4403 typename Proj = std::identity,
4404 typename = internal::range_category_t<Range>,
4405 typename = indirect_result_t<Comp&,
4406 projected<iterator_t<Range>, Proj>,
4407 projected<iterator_t<Range>, Proj>>>
4408 constexpr auto sort_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
4409 return ranges::sort_heap(ranges::begin(range), ranges::end(range),
4410 std::move(comp), std::move(proj));
4411 }
4412
4413 // [is.heap] is_heap
4414 // Reference: https://wg21.link/is.heap
4415
4416 // Returns: Whether the range `[first, last)` is a heap with respect to `comp`
4417 // and `proj`.
4418 //
4419 // Complexity: Linear.
4420 //
4421 // Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap(I
4422 template <typename RandomAccessIterator,
4423 typename Comp = ranges::less,
4424 typename Proj = std::identity,
4425 typename = internal::iterator_category_t<RandomAccessIterator>,
4426 typename = indirect_result_t<Comp&,
4427 projected<RandomAccessIterator, Proj>,
4428 projected<RandomAccessIterator, Proj>>>
4429 constexpr auto is_heap(RandomAccessIterator first,
4430 RandomAccessIterator last,
4431 Comp comp = {},
4432 Proj proj = {}) {
4433 return std::is_heap(first, last,
4434 internal::ProjectedBinaryPredicate(comp, proj, proj));
4435 }
4436
4437 // Returns: Whether `range` is a heap with respect to `comp` and `proj`.
4438 //
4439 // Complexity: Linear.
4440 //
4441 // Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap(R
4442 template <typename Range,
4443 typename Comp = ranges::less,
4444 typename Proj = std::identity,
4445 typename = internal::range_category_t<Range>,
4446 typename = indirect_result_t<Comp&,
4447 projected<iterator_t<Range>, Proj>,
4448 projected<iterator_t<Range>, Proj>>>
4449 constexpr auto is_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
4450 return ranges::is_heap(ranges::begin(range), ranges::end(range),
4451 std::move(comp), std::move(proj));
4452 }
4453
4454 // Returns: The last iterator `i` in `[first, last]` for which the range
4455 // `[first, i)` is a heap with respect to `comp` and `proj`.
4456 //
4457 // Complexity: Linear.
4458 //
4459 // Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap_until(I
4460 template <typename RandomAccessIterator,
4461 typename Comp = ranges::less,
4462 typename Proj = std::identity,
4463 typename = internal::iterator_category_t<RandomAccessIterator>,
4464 typename = indirect_result_t<Comp&,
4465 projected<RandomAccessIterator, Proj>,
4466 projected<RandomAccessIterator, Proj>>>
4467 constexpr auto is_heap_until(RandomAccessIterator first,
4468 RandomAccessIterator last,
4469 Comp comp = {},
4470 Proj proj = {}) {
4471 return std::is_heap_until(
4472 first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
4473 }
4474
4475 // Returns: The last iterator `i` in `[begin(range), end(range)]` for which the
4476 // range `[begin(range), i)` is a heap with respect to `comp` and `proj`.
4477 //
4478 // Complexity: Linear.
4479 //
4480 // Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap_until(R
4481 template <typename Range,
4482 typename Comp = ranges::less,
4483 typename Proj = std::identity,
4484 typename = internal::range_category_t<Range>,
4485 typename = indirect_result_t<Comp&,
4486 projected<iterator_t<Range>, Proj>,
4487 projected<iterator_t<Range>, Proj>>>
4488 constexpr auto is_heap_until(Range&& range, Comp comp = {}, Proj proj = {}) {
4489 return ranges::is_heap_until(ranges::begin(range), ranges::end(range),
4490 std::move(comp), std::move(proj));
4491 }
4492
4493 // [alg.min.max] Minimum and maximum
4494 // Reference: https://wg21.link/alg.min.max
4495
4496 // Returns: The smaller value. Returns the first argument when the arguments are
4497 // equivalent.
4498 //
4499 // Complexity: Exactly one comparison and two applications of the projection, if
4500 // any.
4501 //
4502 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::min
4503 template <typename T,
4504 typename Comp = ranges::less,
4505 typename Proj = std::identity>
4506 constexpr const T& min(const T& a, const T& b, Comp comp = {}, Proj proj = {}) {
4507 return std::invoke(comp, std::invoke(proj, b), std::invoke(proj, a)) ? b : a;
4508 }
4509
4510 // Preconditions: `!empty(ilist)`.
4511 //
4512 // Returns: The smallest value in the input range. Returns a copy of the
4513 // leftmost element when several elements are equivalent to the smallest.
4514 //
4515 // Complexity: Exactly `size(ilist) - 1` comparisons and twice as many
4516 // applications of the projection, if any.
4517 //
4518 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::min(initializer_list
4519 template <typename T,
4520 typename Comp = ranges::less,
4521 typename Proj = std::identity>
4522 constexpr T min(std::initializer_list<T> ilist,
4523 Comp comp = {},
4524 Proj proj = {}) {
4525 return *std::min_element(
4526 ilist.begin(), ilist.end(),
4527 internal::ProjectedBinaryPredicate(comp, proj, proj));
4528 }
4529
4530 // Preconditions: `!empty(range)`.
4531 //
4532 // Returns: The smallest value in the input range. Returns a copy of the
4533 // leftmost element when several elements are equivalent to the smallest.
4534 //
4535 // Complexity: Exactly `size(range) - 1` comparisons and twice as many
4536 // applications of the projection, if any.
4537 //
4538 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::min(R
4539 template <typename Range,
4540 typename Comp = ranges::less,
4541 typename Proj = std::identity,
4542 typename = internal::range_category_t<Range>>
4543 constexpr auto min(Range&& range, Comp comp = {}, Proj proj = {}) {
4544 return *std::min_element(
4545 ranges::begin(range), ranges::end(range),
4546 internal::ProjectedBinaryPredicate(comp, proj, proj));
4547 }
4548
4549 // Returns: The larger value. Returns the first argument when the arguments are
4550 // equivalent.
4551 //
4552 // Complexity: Exactly one comparison and two applications of the projection, if
4553 // any.
4554 //
4555 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::max
4556 template <typename T,
4557 typename Comp = ranges::less,
4558 typename Proj = std::identity>
4559 constexpr const T& max(const T& a, const T& b, Comp comp = {}, Proj proj = {}) {
4560 return std::invoke(comp, std::invoke(proj, a), std::invoke(proj, b)) ? b : a;
4561 }
4562
4563 // Preconditions: `!empty(ilist)`.
4564 //
4565 // Returns: The largest value in the input range. Returns a copy of the leftmost
4566 // element when several elements are equivalent to the largest.
4567 //
4568 // Complexity: Exactly `size(ilist) - 1` comparisons and twice as many
4569 // applications of the projection, if any.
4570 //
4571 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::max(initializer_list
4572 template <typename T,
4573 typename Comp = ranges::less,
4574 typename Proj = std::identity>
4575 constexpr T max(std::initializer_list<T> ilist,
4576 Comp comp = {},
4577 Proj proj = {}) {
4578 return *std::max_element(
4579 ilist.begin(), ilist.end(),
4580 internal::ProjectedBinaryPredicate(comp, proj, proj));
4581 }
4582
4583 // Preconditions: `!empty(range)`.
4584 //
4585 // Returns: The largest value in the input range. Returns a copy of the leftmost
4586 // element when several elements are equivalent to the smallest.
4587 //
4588 // Complexity: Exactly `size(range) - 1` comparisons and twice as many
4589 // applications of the projection, if any.
4590 //
4591 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::max(R
4592 template <typename Range,
4593 typename Comp = ranges::less,
4594 typename Proj = std::identity,
4595 typename = internal::range_category_t<Range>>
4596 constexpr auto max(Range&& range, Comp comp = {}, Proj proj = {}) {
4597 return *std::max_element(
4598 ranges::begin(range), ranges::end(range),
4599 internal::ProjectedBinaryPredicate(comp, proj, proj));
4600 }
4601
4602 // Returns: `{b, a}` if `b` is smaller than `a`, and `{a, b}` otherwise.
4603 //
4604 // Complexity: Exactly one comparison and two applications of the projection, if
4605 // any.
4606 //
4607 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::minmax
4608 template <typename T,
4609 typename Comp = ranges::less,
4610 typename Proj = std::identity>
4611 constexpr auto minmax(const T& a, const T& b, Comp comp = {}, Proj proj = {}) {
4612 return std::minmax(a, b,
4613 internal::ProjectedBinaryPredicate(comp, proj, proj));
4614 }
4615
4616 // Preconditions: `!empty(ilist)`.
4617 //
4618 // Returns: Let `X` be the return type. Returns `X{x, y}`, where `x` is a copy
4619 // of the leftmost element with the smallest value and `y` a copy of the
4620 // rightmost element with the largest value in the input range.
4621 //
4622 // Complexity: At most `(3/2) size(ilist)` applications of the corresponding
4623 // predicate and twice as many applications of the projection, if any.
4624 //
4625 // Reference:
4626 // https://wg21.link/alg.min.max#:~:text=ranges::minmax(initializer_list
4627 template <typename T,
4628 typename Comp = ranges::less,
4629 typename Proj = std::identity>
4630 constexpr auto minmax(std::initializer_list<T> ilist,
4631 Comp comp = {},
4632 Proj proj = {}) {
4633 auto it =
4634 std::minmax_element(ranges::begin(ilist), ranges::end(ilist),
4635 internal::ProjectedBinaryPredicate(comp, proj, proj));
4636 return std::pair<T, T>{*it.first, *it.second};
4637 }
4638
4639 // Preconditions: `!empty(range)`.
4640 //
4641 // Returns: Let `X` be the return type. Returns `X{x, y}`, where `x` is a copy
4642 // of the leftmost element with the smallest value and `y` a copy of the
4643 // rightmost element with the largest value in the input range.
4644 //
4645 // Complexity: At most `(3/2) size(range)` applications of the corresponding
4646 // predicate and twice as many applications of the projection, if any.
4647 //
4648 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::minmax(R
4649 template <typename Range,
4650 typename Comp = ranges::less,
4651 typename Proj = std::identity,
4652 typename = internal::range_category_t<Range>>
4653 constexpr auto minmax(Range&& range, Comp comp = {}, Proj proj = {}) {
4654 using T = range_value_t<Range>;
4655 auto it =
4656 std::minmax_element(ranges::begin(range), ranges::end(range),
4657 internal::ProjectedBinaryPredicate(comp, proj, proj));
4658 return std::pair<T, T>{*it.first, *it.second};
4659 }
4660
4661 // Returns: The first iterator i in the range `[first, last)` such that for
4662 // every iterator `j` in the range `[first, last)`,
4663 // `bool(invoke(comp, invoke(proj, *j), invoke(proj, *i)))` is `false`. Returns
4664 // `last` if `first == last`.
4665 //
4666 // Complexity: Exactly `max(last - first - 1, 0)` comparisons and twice as
4667 // many projections.
4668 //
4669 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::min_element(I
4670 template <typename ForwardIterator,
4671 typename Comp = ranges::less,
4672 typename Proj = std::identity,
4673 typename = internal::iterator_category_t<ForwardIterator>,
4674 typename = indirect_result_t<Comp&,
4675 projected<ForwardIterator, Proj>,
4676 projected<ForwardIterator, Proj>>>
4677 constexpr auto min_element(ForwardIterator first,
4678 ForwardIterator last,
4679 Comp comp = {},
4680 Proj proj = {}) {
4681 return std::min_element(first, last,
4682 internal::ProjectedBinaryPredicate(comp, proj, proj));
4683 }
4684
4685 // Returns: The first iterator i in `range` such that for every iterator `j` in
4686 // `range`, `bool(invoke(comp, invoke(proj, *j), invoke(proj, *i)))` is `false`.
4687 // Returns `end(range)` if `empty(range)`.
4688 //
4689 // Complexity: Exactly `max(size(range) - 1, 0)` comparisons and twice as many
4690 // projections.
4691 //
4692 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::min_element(R
4693 template <typename Range,
4694 typename Comp = ranges::less,
4695 typename Proj = std::identity,
4696 typename = internal::range_category_t<Range>,
4697 typename = indirect_result_t<Comp&,
4698 projected<iterator_t<Range>, Proj>,
4699 projected<iterator_t<Range>, Proj>>>
4700 constexpr auto min_element(Range&& range, Comp comp = {}, Proj proj = {}) {
4701 return ranges::min_element(ranges::begin(range), ranges::end(range),
4702 std::move(comp), std::move(proj));
4703 }
4704
4705 // Returns: The first iterator i in the range `[first, last)` such that for
4706 // every iterator `j` in the range `[first, last)`,
4707 // `bool(invoke(comp, invoke(proj, *i), invoke(proj, *j)))` is `false`.
4708 // Returns `last` if `first == last`.
4709 //
4710 // Complexity: Exactly `max(last - first - 1, 0)` comparisons and twice as
4711 // many projections.
4712 //
4713 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::max_element(I
4714 template <typename ForwardIterator,
4715 typename Comp = ranges::less,
4716 typename Proj = std::identity,
4717 typename = internal::iterator_category_t<ForwardIterator>,
4718 typename = indirect_result_t<Comp&,
4719 projected<ForwardIterator, Proj>,
4720 projected<ForwardIterator, Proj>>>
4721 constexpr auto max_element(ForwardIterator first,
4722 ForwardIterator last,
4723 Comp comp = {},
4724 Proj proj = {}) {
4725 return std::max_element(first, last,
4726 internal::ProjectedBinaryPredicate(comp, proj, proj));
4727 }
4728
4729 // Returns: The first iterator i in `range` such that for every iterator `j`
4730 // in `range`, `bool(invoke(comp, invoke(proj, *j), invoke(proj, *j)))` is
4731 // `false`. Returns `end(range)` if `empty(range)`.
4732 //
4733 // Complexity: Exactly `max(size(range) - 1, 0)` comparisons and twice as many
4734 // projections.
4735 //
4736 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::max_element(R
4737 template <typename Range,
4738 typename Comp = ranges::less,
4739 typename Proj = std::identity,
4740 typename = internal::range_category_t<Range>,
4741 typename = indirect_result_t<Comp&,
4742 projected<iterator_t<Range>, Proj>,
4743 projected<iterator_t<Range>, Proj>>>
4744 constexpr auto max_element(Range&& range, Comp comp = {}, Proj proj = {}) {
4745 return ranges::max_element(ranges::begin(range), ranges::end(range),
4746 std::move(comp), std::move(proj));
4747 }
4748
4749 // Returns: `{first, first}` if `[first, last)` is empty, otherwise `{m, M}`,
4750 // where `m` is the first iterator in `[first, last)` such that no iterator in
4751 // the range refers to a smaller element, and where `M` is the last iterator
4752 // in
4753 // `[first, last)` such that no iterator in the range refers to a larger
4754 // element.
4755 //
4756 // Complexity: Let `N` be `last - first`. At most `max(3/2 (N − 1), 0)`
4757 // comparisons and twice as many applications of the projection, if any.
4758 //
4759 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::minmax_element(I
4760 template <typename ForwardIterator,
4761 typename Comp = ranges::less,
4762 typename Proj = std::identity,
4763 typename = internal::iterator_category_t<ForwardIterator>,
4764 typename = indirect_result_t<Comp&,
4765 projected<ForwardIterator, Proj>,
4766 projected<ForwardIterator, Proj>>>
4767 constexpr auto minmax_element(ForwardIterator first,
4768 ForwardIterator last,
4769 Comp comp = {},
4770 Proj proj = {}) {
4771 return std::minmax_element(
4772 first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
4773 }
4774
4775 // Returns: `{begin(range), begin(range)}` if `range` is empty, otherwise
4776 // `{m, M}`, where `m` is the first iterator in `range` such that no iterator
4777 // in the range refers to a smaller element, and where `M` is the last
4778 // iterator in `range` such that no iterator in the range refers to a larger
4779 // element.
4780 //
4781 // Complexity: Let `N` be `size(range)`. At most `max(3/2 (N − 1), 0)`
4782 // comparisons and twice as many applications of the projection, if any.
4783 //
4784 // Reference: https://wg21.link/alg.min.max#:~:text=ranges::minmax_element(R
4785 template <typename Range,
4786 typename Comp = ranges::less,
4787 typename Proj = std::identity,
4788 typename = internal::range_category_t<Range>,
4789 typename = indirect_result_t<Comp&,
4790 projected<iterator_t<Range>, Proj>,
4791 projected<iterator_t<Range>, Proj>>>
4792 constexpr auto minmax_element(Range&& range, Comp comp = {}, Proj proj = {}) {
4793 return ranges::minmax_element(ranges::begin(range), ranges::end(range),
4794 std::move(comp), std::move(proj));
4795 }
4796
4797 // [alg.clamp] Bounded value
4798 // Reference: https://wg21.link/alg.clamp
4799
4800 // Preconditions: `bool(invoke(comp, invoke(proj, hi), invoke(proj, lo)))` is
4801 // `false`.
4802 //
4803 // Returns: `lo` if `bool(invoke(comp, invoke(proj, v), invoke(proj, lo)))` is
4804 // `true`, `hi` if `bool(invoke(comp, invoke(proj, hi), invoke(proj, v)))` is
4805 // `true`, otherwise `v`.
4806 //
4807 // Complexity: At most two comparisons and three applications of the
4808 // projection.
4809 //
4810 // Reference: https://wg21.link/alg.clamp#:~:text=ranges::clamp
4811 template <typename T,
4812 typename Comp = ranges::less,
4813 typename Proj = std::identity>
4814 constexpr const T& clamp(const T& v,
4815 const T& lo,
4816 const T& hi,
4817 Comp comp = {},
4818 Proj proj = {}) {
4819 auto&& projected_v = std::invoke(proj, v);
4820 if (std::invoke(comp, projected_v, std::invoke(proj, lo))) {
4821 return lo;
4822 }
4823
4824 return std::invoke(comp, std::invoke(proj, hi), projected_v) ? hi : v;
4825 }
4826
4827 // [alg.lex.comparison] Lexicographical comparison
4828 // Reference: https://wg21.link/alg.lex.comparison
4829
4830 // Returns: `true` if and only if the sequence of elements defined by the range
4831 // `[first1, last1)` is lexicographically less than the sequence of elements
4832 // defined by the range `[first2, last2)`.
4833 //
4834 // Complexity: At most `2 min(last1 - first1, last2 - first2)` applications of
4835 // the corresponding comparison and each projection, if any.
4836 //
4837 // Remarks: If two sequences have the same number of elements and their
4838 // corresponding elements (if any) are equivalent, then neither sequence is
4839 // lexicographically less than the other. If one sequence is a proper prefix of
4840 // the other, then the shorter sequence is lexicographically less than the
4841 // longer sequence. Otherwise, the lexicographical comparison of the sequences
4842 // yields the same result as the comparison of the first corresponding pair of
4843 // elements that are not equivalent.
4844 //
4845 // Reference:
4846 // https://wg21.link/alg.lex.comparison#:~:text=lexicographical_compare(I1
4847 template <typename ForwardIterator1,
4848 typename ForwardIterator2,
4849 typename Comp = ranges::less,
4850 typename Proj1 = std::identity,
4851 typename Proj2 = std::identity,
4852 typename = internal::iterator_category_t<ForwardIterator1>,
4853 typename = internal::iterator_category_t<ForwardIterator2>,
4854 typename = indirect_result_t<Comp&,
4855 projected<ForwardIterator1, Proj1>,
4856 projected<ForwardIterator2, Proj2>>,
4857 typename = indirect_result_t<Comp&,
4858 projected<ForwardIterator2, Proj2>,
4859 projected<ForwardIterator1, Proj1>>>
4860 constexpr bool lexicographical_compare(ForwardIterator1 first1,
4861 ForwardIterator1 last1,
4862 ForwardIterator2 first2,
4863 ForwardIterator2 last2,
4864 Comp comp = {},
4865 Proj1 proj1 = {},
4866 Proj2 proj2 = {}) {
4867 for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
4868 auto&& projected_first1 = std::invoke(proj1, *first1);
4869 auto&& projected_first2 = std::invoke(proj2, *first2);
4870 if (std::invoke(comp, projected_first1, projected_first2)) {
4871 return true;
4872 }
4873 if (std::invoke(comp, projected_first2, projected_first1)) {
4874 return false;
4875 }
4876 }
4877
4878 // `first2 != last2` is equivalent to `first1 == last1 && first2 != last2`
4879 // here, since we broke out of the loop above.
4880 return first2 != last2;
4881 }
4882
4883 // Returns: `true` if and only if the sequence of elements defined by `range1`
4884 // is lexicographically less than the sequence of elements defined by `range2`.
4885 //
4886 // Complexity: At most `2 min(size(range1), size(range2))` applications of the
4887 // corresponding comparison and each projection, if any.
4888 //
4889 // Remarks: If two sequences have the same number of elements and their
4890 // corresponding elements (if any) are equivalent, then neither sequence is
4891 // lexicographically less than the other. If one sequence is a proper prefix of
4892 // the other, then the shorter sequence is lexicographically less than the
4893 // longer sequence. Otherwise, the lexicographical comparison of the sequences
4894 // yields the same result as the comparison of the first corresponding pair of
4895 // elements that are not equivalent.
4896 //
4897 // Reference:
4898 // https://wg21.link/alg.lex.comparison#:~:text=lexicographical_compare(R1
4899 template <typename Range1,
4900 typename Range2,
4901 typename Comp = ranges::less,
4902 typename Proj1 = std::identity,
4903 typename Proj2 = std::identity,
4904 typename = internal::range_category_t<Range1>,
4905 typename = internal::range_category_t<Range2>,
4906 typename = indirect_result_t<Comp&,
4907 projected<iterator_t<Range1>, Proj1>,
4908 projected<iterator_t<Range2>, Proj2>>,
4909 typename = indirect_result_t<Comp&,
4910 projected<iterator_t<Range2>, Proj2>,
4911 projected<iterator_t<Range1>, Proj1>>>
4912 constexpr bool lexicographical_compare(Range1&& range1,
4913 Range2&& range2,
4914 Comp comp = {},
4915 Proj1 proj1 = {},
4916 Proj2 proj2 = {}) {
4917 return ranges::lexicographical_compare(
4918 ranges::begin(range1), ranges::end(range1), ranges::begin(range2),
4919 ranges::end(range2), std::move(comp), std::move(proj1), std::move(proj2));
4920 }
4921
4922 // [alg.permutation.generators] Permutation generators
4923 // Reference: https://wg21.link/alg.permutation.generators
4924
4925 // Effects: Takes a sequence defined by the range `[first, last)` and transforms
4926 // it into the next permutation. The next permutation is found by assuming that
4927 // the set of all permutations is lexicographically sorted with respect to
4928 // `comp` and `proj`. If no such permutation exists, transforms the sequence
4929 // into the first permutation; that is, the ascendingly-sorted one.
4930 //
4931 // Returns: `true` if a next permutation was found and otherwise `false`.
4932 //
4933 // Complexity: At most `(last - first) / 2` swaps.
4934 //
4935 // Reference:
4936 // https://wg21.link/alg.permutation.generators#:~:text=next_permutation(I
4937 template <typename BidirectionalIterator,
4938 typename Comp = ranges::less,
4939 typename Proj = std::identity,
4940 typename = internal::iterator_category_t<BidirectionalIterator>,
4941 typename = indirect_result_t<Comp&,
4942 projected<BidirectionalIterator, Proj>,
4943 projected<BidirectionalIterator, Proj>>>
4944 constexpr auto next_permutation(BidirectionalIterator first,
4945 BidirectionalIterator last,
4946 Comp comp = {},
4947 Proj proj = {}) {
4948 return std::next_permutation(
4949 first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
4950 }
4951
4952 // Effects: Takes a sequence defined by `range` and transforms it into the next
4953 // permutation. The next permutation is found by assuming that the set of all
4954 // permutations is lexicographically sorted with respect to `comp` and `proj`.
4955 // If no such permutation exists, transforms the sequence into the first
4956 // permutation; that is, the ascendingly-sorted one.
4957 //
4958 // Returns: `true` if a next permutation was found and otherwise `false`.
4959 //
4960 // Complexity: At most `size(range) / 2` swaps.
4961 //
4962 // Reference:
4963 // https://wg21.link/alg.permutation.generators#:~:text=next_permutation(R
4964 template <typename Range,
4965 typename Comp = ranges::less,
4966 typename Proj = std::identity,
4967 typename = internal::range_category_t<Range>,
4968 typename = indirect_result_t<Comp&,
4969 projected<iterator_t<Range>, Proj>,
4970 projected<iterator_t<Range>, Proj>>>
4971 constexpr auto next_permutation(Range&& range, Comp comp = {}, Proj proj = {}) {
4972 return ranges::next_permutation(ranges::begin(range), ranges::end(range),
4973 std::move(comp), std::move(proj));
4974 }
4975
4976 // Effects: Takes a sequence defined by the range `[first, last)` and transforms
4977 // it into the previous permutation. The previous permutation is found by
4978 // assuming that the set of all permutations is lexicographically sorted with
4979 // respect to `comp` and `proj`. If no such permutation exists, transforms the
4980 // sequence into the last permutation; that is, the decreasingly-sorted one.
4981 //
4982 // Returns: `true` if a next permutation was found and otherwise `false`.
4983 //
4984 // Complexity: At most `(last - first) / 2` swaps.
4985 //
4986 // Reference:
4987 // https://wg21.link/alg.permutation.generators#:~:text=prev_permutation(I
4988 template <typename BidirectionalIterator,
4989 typename Comp = ranges::less,
4990 typename Proj = std::identity,
4991 typename = internal::iterator_category_t<BidirectionalIterator>,
4992 typename = indirect_result_t<Comp&,
4993 projected<BidirectionalIterator, Proj>,
4994 projected<BidirectionalIterator, Proj>>>
4995 constexpr auto prev_permutation(BidirectionalIterator first,
4996 BidirectionalIterator last,
4997 Comp comp = {},
4998 Proj proj = {}) {
4999 return std::prev_permutation(
5000 first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
5001 }
5002
5003 // Effects: Takes a sequence defined by `range` and transforms it into the
5004 // previous permutation. The previous permutation is found by assuming that the
5005 // set of all permutations is lexicographically sorted with respect to `comp`
5006 // and `proj`. If no such permutation exists, transforms the sequence into the
5007 // last permutation; that is, the decreasingly-sorted one.
5008 //
5009 // Returns: `true` if a previous permutation was found and otherwise `false`.
5010 //
5011 // Complexity: At most `size(range) / 2` swaps.
5012 //
5013 // Reference:
5014 // https://wg21.link/alg.permutation.generators#:~:text=prev_permutation(R
5015 template <typename Range,
5016 typename Comp = ranges::less,
5017 typename Proj = std::identity,
5018 typename = internal::range_category_t<Range>,
5019 typename = indirect_result_t<Comp&,
5020 projected<iterator_t<Range>, Proj>,
5021 projected<iterator_t<Range>, Proj>>>
5022 constexpr auto prev_permutation(Range&& range, Comp comp = {}, Proj proj = {}) {
5023 return ranges::prev_permutation(ranges::begin(range), ranges::end(range),
5024 std::move(comp), std::move(proj));
5025 }
5026
5027 } // namespace ranges
5028
5029 } // namespace base
5030
5031 #endif // BASE_RANGES_ALGORITHM_H_
5032