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