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