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