tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

container.h (81319B)


      1 // Copyright 2017 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 //
     15 // -----------------------------------------------------------------------------
     16 // File: container.h
     17 // -----------------------------------------------------------------------------
     18 //
     19 // This header file provides Container-based versions of algorithmic functions
     20 // within the C++ standard library. The following standard library sets of
     21 // functions are covered within this file:
     22 //
     23 //   * Algorithmic <iterator> functions
     24 //   * Algorithmic <numeric> functions
     25 //   * <algorithm> functions
     26 //
     27 // The standard library functions operate on iterator ranges; the functions
     28 // within this API operate on containers, though many return iterator ranges.
     29 //
     30 // All functions within this API are named with a `c_` prefix. Calls such as
     31 // `absl::c_xx(container, ...) are equivalent to std:: functions such as
     32 // `std::xx(std::begin(cont), std::end(cont), ...)`. Functions that act on
     33 // iterators but not conceptually on iterator ranges (e.g. `std::iter_swap`)
     34 // have no equivalent here.
     35 //
     36 // For template parameter and variable naming, `C` indicates the container type
     37 // to which the function is applied, `Pred` indicates the predicate object type
     38 // to be used by the function and `T` indicates the applicable element type.
     39 
     40 #ifndef ABSL_ALGORITHM_CONTAINER_H_
     41 #define ABSL_ALGORITHM_CONTAINER_H_
     42 
     43 #include <algorithm>
     44 #include <cassert>
     45 #include <iterator>
     46 #include <numeric>
     47 #include <random>
     48 #include <type_traits>
     49 #include <unordered_map>
     50 #include <unordered_set>
     51 #include <utility>
     52 #include <vector>
     53 
     54 #include "absl/algorithm/algorithm.h"
     55 #include "absl/base/config.h"
     56 #include "absl/base/macros.h"
     57 #include "absl/base/nullability.h"
     58 #include "absl/meta/type_traits.h"
     59 
     60 namespace absl {
     61 ABSL_NAMESPACE_BEGIN
     62 namespace container_algorithm_internal {
     63 
     64 // NOTE: it is important to defer to ADL lookup for building with C++ modules,
     65 // especially for headers like <valarray> which are not visible from this file
     66 // but specialize std::begin and std::end.
     67 using std::begin;
     68 using std::end;
     69 
     70 // The type of the iterator given by begin(c) (possibly std::begin(c)).
     71 // ContainerIter<const vector<T>> gives vector<T>::const_iterator,
     72 // while ContainerIter<vector<T>> gives vector<T>::iterator.
     73 template <typename C>
     74 using ContainerIter = decltype(begin(std::declval<C&>()));
     75 
     76 // An MSVC bug involving template parameter substitution requires us to use
     77 // decltype() here instead of just std::pair.
     78 template <typename C1, typename C2>
     79 using ContainerIterPairType =
     80    decltype(std::make_pair(ContainerIter<C1>(), ContainerIter<C2>()));
     81 
     82 template <typename C>
     83 using ContainerDifferenceType = decltype(std::distance(
     84    std::declval<ContainerIter<C>>(), std::declval<ContainerIter<C>>()));
     85 
     86 template <typename C>
     87 using ContainerPointerType =
     88    typename std::iterator_traits<ContainerIter<C>>::pointer;
     89 
     90 // container_algorithm_internal::c_begin and
     91 // container_algorithm_internal::c_end are abbreviations for proper ADL
     92 // lookup of std::begin and std::end, i.e.
     93 //   using std::begin;
     94 //   using std::end;
     95 //   std::foo(begin(c), end(c));
     96 // becomes
     97 //   std::foo(container_algorithm_internal::c_begin(c),
     98 //            container_algorithm_internal::c_end(c));
     99 // These are meant for internal use only.
    100 
    101 template <typename C>
    102 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) {
    103  return begin(c);
    104 }
    105 
    106 template <typename C>
    107 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) {
    108  return end(c);
    109 }
    110 
    111 template <typename T>
    112 struct IsUnorderedContainer : std::false_type {};
    113 
    114 template <class Key, class T, class Hash, class KeyEqual, class Allocator>
    115 struct IsUnorderedContainer<
    116    std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
    117 
    118 template <class Key, class Hash, class KeyEqual, class Allocator>
    119 struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
    120    : std::true_type {};
    121 
    122 }  // namespace container_algorithm_internal
    123 
    124 // PUBLIC API
    125 
    126 //------------------------------------------------------------------------------
    127 // Abseil algorithm.h functions
    128 //------------------------------------------------------------------------------
    129 
    130 // c_linear_search()
    131 //
    132 // Container-based version of absl::linear_search() for performing a linear
    133 // search within a container.
    134 //
    135 // For a generalization that uses a predicate, see absl::c_any_of().
    136 template <typename C, typename EqualityComparable>
    137 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search(
    138    const C& c, EqualityComparable&& value) {
    139  return absl::linear_search(container_algorithm_internal::c_begin(c),
    140                             container_algorithm_internal::c_end(c),
    141                             std::forward<EqualityComparable>(value));
    142 }
    143 
    144 //------------------------------------------------------------------------------
    145 // <iterator> algorithms
    146 //------------------------------------------------------------------------------
    147 
    148 // c_distance()
    149 //
    150 // Container-based version of the <iterator> `std::distance()` function to
    151 // return the number of elements within a container.
    152 template <typename C>
    153 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
    154    container_algorithm_internal::ContainerDifferenceType<const C>
    155    c_distance(const C& c) {
    156  return std::distance(container_algorithm_internal::c_begin(c),
    157                       container_algorithm_internal::c_end(c));
    158 }
    159 
    160 //------------------------------------------------------------------------------
    161 // <algorithm> Non-modifying sequence operations
    162 //------------------------------------------------------------------------------
    163 
    164 // c_all_of()
    165 //
    166 // Container-based version of the <algorithm> `std::all_of()` function to
    167 // test if all elements within a container satisfy a condition.
    168 template <typename C, typename Pred>
    169 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) {
    170  return std::all_of(container_algorithm_internal::c_begin(c),
    171                     container_algorithm_internal::c_end(c),
    172                     std::forward<Pred>(pred));
    173 }
    174 
    175 // c_any_of()
    176 //
    177 // Container-based version of the <algorithm> `std::any_of()` function to
    178 // test if any element in a container fulfills a condition.
    179 template <typename C, typename Pred>
    180 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) {
    181  return std::any_of(container_algorithm_internal::c_begin(c),
    182                     container_algorithm_internal::c_end(c),
    183                     std::forward<Pred>(pred));
    184 }
    185 
    186 // c_none_of()
    187 //
    188 // Container-based version of the <algorithm> `std::none_of()` function to
    189 // test if no elements in a container fulfill a condition.
    190 template <typename C, typename Pred>
    191 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) {
    192  return std::none_of(container_algorithm_internal::c_begin(c),
    193                      container_algorithm_internal::c_end(c),
    194                      std::forward<Pred>(pred));
    195 }
    196 
    197 // c_for_each()
    198 //
    199 // Container-based version of the <algorithm> `std::for_each()` function to
    200 // apply a function to a container's elements.
    201 template <typename C, typename Function>
    202 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<Function> c_for_each(C&& c,
    203                                                                 Function&& f) {
    204  return std::for_each(container_algorithm_internal::c_begin(c),
    205                       container_algorithm_internal::c_end(c),
    206                       std::forward<Function>(f));
    207 }
    208 
    209 // c_find()
    210 //
    211 // Container-based version of the <algorithm> `std::find()` function to find
    212 // the first element containing the passed value within a container value.
    213 template <typename C, typename T>
    214 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    215    container_algorithm_internal::ContainerIter<C>
    216    c_find(C& c, T&& value) {
    217  return std::find(container_algorithm_internal::c_begin(c),
    218                   container_algorithm_internal::c_end(c),
    219                   std::forward<T>(value));
    220 }
    221 
    222 // c_contains()
    223 //
    224 // Container-based version of the <algorithm> `std::ranges::contains()` C++23
    225 // function to search a container for a value.
    226 template <typename Sequence, typename T>
    227 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence,
    228                                                    T&& value) {
    229  return absl::c_find(sequence, std::forward<T>(value)) !=
    230         container_algorithm_internal::c_end(sequence);
    231 }
    232 
    233 // c_find_if()
    234 //
    235 // Container-based version of the <algorithm> `std::find_if()` function to find
    236 // the first element in a container matching the given condition.
    237 template <typename C, typename Pred>
    238 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    239    container_algorithm_internal::ContainerIter<C>
    240    c_find_if(C& c, Pred&& pred) {
    241  return std::find_if(container_algorithm_internal::c_begin(c),
    242                      container_algorithm_internal::c_end(c),
    243                      std::forward<Pred>(pred));
    244 }
    245 
    246 // c_find_if_not()
    247 //
    248 // Container-based version of the <algorithm> `std::find_if_not()` function to
    249 // find the first element in a container not matching the given condition.
    250 template <typename C, typename Pred>
    251 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    252    container_algorithm_internal::ContainerIter<C>
    253    c_find_if_not(C& c, Pred&& pred) {
    254  return std::find_if_not(container_algorithm_internal::c_begin(c),
    255                          container_algorithm_internal::c_end(c),
    256                          std::forward<Pred>(pred));
    257 }
    258 
    259 // c_find_end()
    260 //
    261 // Container-based version of the <algorithm> `std::find_end()` function to
    262 // find the last subsequence within a container.
    263 template <typename Sequence1, typename Sequence2>
    264 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    265    container_algorithm_internal::ContainerIter<Sequence1>
    266    c_find_end(Sequence1& sequence, Sequence2& subsequence) {
    267  return std::find_end(container_algorithm_internal::c_begin(sequence),
    268                       container_algorithm_internal::c_end(sequence),
    269                       container_algorithm_internal::c_begin(subsequence),
    270                       container_algorithm_internal::c_end(subsequence));
    271 }
    272 
    273 // Overload of c_find_end() for using a predicate evaluation other than `==` as
    274 // the function's test condition.
    275 template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
    276 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    277    container_algorithm_internal::ContainerIter<Sequence1>
    278    c_find_end(Sequence1& sequence, Sequence2& subsequence,
    279               BinaryPredicate&& pred) {
    280  return std::find_end(container_algorithm_internal::c_begin(sequence),
    281                       container_algorithm_internal::c_end(sequence),
    282                       container_algorithm_internal::c_begin(subsequence),
    283                       container_algorithm_internal::c_end(subsequence),
    284                       std::forward<BinaryPredicate>(pred));
    285 }
    286 
    287 // c_find_first_of()
    288 //
    289 // Container-based version of the <algorithm> `std::find_first_of()` function to
    290 // find the first element within the container that is also within the options
    291 // container.
    292 template <typename C1, typename C2>
    293 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    294    container_algorithm_internal::ContainerIter<C1>
    295    c_find_first_of(C1& container, const C2& options) {
    296  return std::find_first_of(container_algorithm_internal::c_begin(container),
    297                            container_algorithm_internal::c_end(container),
    298                            container_algorithm_internal::c_begin(options),
    299                            container_algorithm_internal::c_end(options));
    300 }
    301 
    302 // Overload of c_find_first_of() for using a predicate evaluation other than
    303 // `==` as the function's test condition.
    304 template <typename C1, typename C2, typename BinaryPredicate>
    305 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    306    container_algorithm_internal::ContainerIter<C1>
    307    c_find_first_of(C1& container, const C2& options, BinaryPredicate&& pred) {
    308  return std::find_first_of(container_algorithm_internal::c_begin(container),
    309                            container_algorithm_internal::c_end(container),
    310                            container_algorithm_internal::c_begin(options),
    311                            container_algorithm_internal::c_end(options),
    312                            std::forward<BinaryPredicate>(pred));
    313 }
    314 
    315 // c_adjacent_find()
    316 //
    317 // Container-based version of the <algorithm> `std::adjacent_find()` function to
    318 // find equal adjacent elements within a container.
    319 template <typename Sequence>
    320 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    321    container_algorithm_internal::ContainerIter<Sequence>
    322    c_adjacent_find(Sequence& sequence) {
    323  return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
    324                            container_algorithm_internal::c_end(sequence));
    325 }
    326 
    327 // Overload of c_adjacent_find() for using a predicate evaluation other than
    328 // `==` as the function's test condition.
    329 template <typename Sequence, typename BinaryPredicate>
    330 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    331    container_algorithm_internal::ContainerIter<Sequence>
    332    c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) {
    333  return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
    334                            container_algorithm_internal::c_end(sequence),
    335                            std::forward<BinaryPredicate>(pred));
    336 }
    337 
    338 // c_count()
    339 //
    340 // Container-based version of the <algorithm> `std::count()` function to count
    341 // values that match within a container.
    342 template <typename C, typename T>
    343 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    344    container_algorithm_internal::ContainerDifferenceType<const C>
    345    c_count(const C& c, T&& value) {
    346  return std::count(container_algorithm_internal::c_begin(c),
    347                    container_algorithm_internal::c_end(c),
    348                    std::forward<T>(value));
    349 }
    350 
    351 // c_count_if()
    352 //
    353 // Container-based version of the <algorithm> `std::count_if()` function to
    354 // count values matching a condition within a container.
    355 template <typename C, typename Pred>
    356 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    357    container_algorithm_internal::ContainerDifferenceType<const C>
    358    c_count_if(const C& c, Pred&& pred) {
    359  return std::count_if(container_algorithm_internal::c_begin(c),
    360                       container_algorithm_internal::c_end(c),
    361                       std::forward<Pred>(pred));
    362 }
    363 
    364 // c_mismatch()
    365 //
    366 // Container-based version of the <algorithm> `std::mismatch()` function to
    367 // return the first element where two ordered containers differ. Applies `==` to
    368 // the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
    369 template <typename C1, typename C2>
    370 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    371    container_algorithm_internal::ContainerIterPairType<C1, C2>
    372    c_mismatch(C1& c1, C2& c2) {
    373  return std::mismatch(container_algorithm_internal::c_begin(c1),
    374                       container_algorithm_internal::c_end(c1),
    375                       container_algorithm_internal::c_begin(c2),
    376                       container_algorithm_internal::c_end(c2));
    377 }
    378 
    379 // Overload of c_mismatch() for using a predicate evaluation other than `==` as
    380 // the function's test condition. Applies `pred`to the first N elements of `c1`
    381 // and `c2`, where N = min(size(c1), size(c2)).
    382 template <typename C1, typename C2, typename BinaryPredicate>
    383 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    384    container_algorithm_internal::ContainerIterPairType<C1, C2>
    385    c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
    386  return std::mismatch(container_algorithm_internal::c_begin(c1),
    387                       container_algorithm_internal::c_end(c1),
    388                       container_algorithm_internal::c_begin(c2),
    389                       container_algorithm_internal::c_end(c2), pred);
    390 }
    391 
    392 // c_equal()
    393 //
    394 // Container-based version of the <algorithm> `std::equal()` function to
    395 // test whether two containers are equal.
    396 template <typename C1, typename C2>
    397 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2) {
    398  return std::equal(container_algorithm_internal::c_begin(c1),
    399                    container_algorithm_internal::c_end(c1),
    400                    container_algorithm_internal::c_begin(c2),
    401                    container_algorithm_internal::c_end(c2));
    402 }
    403 
    404 // Overload of c_equal() for using a predicate evaluation other than `==` as
    405 // the function's test condition.
    406 template <typename C1, typename C2, typename BinaryPredicate>
    407 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2,
    408                                                 BinaryPredicate&& pred) {
    409  return std::equal(container_algorithm_internal::c_begin(c1),
    410                    container_algorithm_internal::c_end(c1),
    411                    container_algorithm_internal::c_begin(c2),
    412                    container_algorithm_internal::c_end(c2),
    413                    std::forward<BinaryPredicate>(pred));
    414 }
    415 
    416 // c_is_permutation()
    417 //
    418 // Container-based version of the <algorithm> `std::is_permutation()` function
    419 // to test whether a container is a permutation of another.
    420 template <typename C1, typename C2>
    421 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(const C1& c1,
    422                                                          const C2& c2) {
    423  return std::is_permutation(container_algorithm_internal::c_begin(c1),
    424                             container_algorithm_internal::c_end(c1),
    425                             container_algorithm_internal::c_begin(c2),
    426                             container_algorithm_internal::c_end(c2));
    427 }
    428 
    429 // Overload of c_is_permutation() for using a predicate evaluation other than
    430 // `==` as the function's test condition.
    431 template <typename C1, typename C2, typename BinaryPredicate>
    432 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(
    433    const C1& c1, const C2& c2, BinaryPredicate&& pred) {
    434  return std::is_permutation(container_algorithm_internal::c_begin(c1),
    435                             container_algorithm_internal::c_end(c1),
    436                             container_algorithm_internal::c_begin(c2),
    437                             container_algorithm_internal::c_end(c2),
    438                             std::forward<BinaryPredicate>(pred));
    439 }
    440 
    441 // c_search()
    442 //
    443 // Container-based version of the <algorithm> `std::search()` function to search
    444 // a container for a subsequence.
    445 template <typename Sequence1, typename Sequence2>
    446 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    447    container_algorithm_internal::ContainerIter<Sequence1>
    448    c_search(Sequence1& sequence, Sequence2& subsequence) {
    449  return std::search(container_algorithm_internal::c_begin(sequence),
    450                     container_algorithm_internal::c_end(sequence),
    451                     container_algorithm_internal::c_begin(subsequence),
    452                     container_algorithm_internal::c_end(subsequence));
    453 }
    454 
    455 // Overload of c_search() for using a predicate evaluation other than
    456 // `==` as the function's test condition.
    457 template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
    458 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    459    container_algorithm_internal::ContainerIter<Sequence1>
    460    c_search(Sequence1& sequence, Sequence2& subsequence,
    461             BinaryPredicate&& pred) {
    462  return std::search(container_algorithm_internal::c_begin(sequence),
    463                     container_algorithm_internal::c_end(sequence),
    464                     container_algorithm_internal::c_begin(subsequence),
    465                     container_algorithm_internal::c_end(subsequence),
    466                     std::forward<BinaryPredicate>(pred));
    467 }
    468 
    469 // c_contains_subrange()
    470 //
    471 // Container-based version of the <algorithm> `std::ranges::contains_subrange()`
    472 // C++23 function to search a container for a subsequence.
    473 template <typename Sequence1, typename Sequence2>
    474 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(
    475    Sequence1& sequence, Sequence2& subsequence) {
    476  return absl::c_search(sequence, subsequence) !=
    477         container_algorithm_internal::c_end(sequence);
    478 }
    479 
    480 // Overload of c_contains_subrange() for using a predicate evaluation other than
    481 // `==` as the function's test condition.
    482 template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
    483 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(
    484    Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
    485  return absl::c_search(sequence, subsequence,
    486                        std::forward<BinaryPredicate>(pred)) !=
    487         container_algorithm_internal::c_end(sequence);
    488 }
    489 
    490 // c_search_n()
    491 //
    492 // Container-based version of the <algorithm> `std::search_n()` function to
    493 // search a container for the first sequence of N elements.
    494 template <typename Sequence, typename Size, typename T>
    495 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    496    container_algorithm_internal::ContainerIter<Sequence>
    497    c_search_n(Sequence& sequence, Size count, T&& value) {
    498  return std::search_n(container_algorithm_internal::c_begin(sequence),
    499                       container_algorithm_internal::c_end(sequence), count,
    500                       std::forward<T>(value));
    501 }
    502 
    503 // Overload of c_search_n() for using a predicate evaluation other than
    504 // `==` as the function's test condition.
    505 template <typename Sequence, typename Size, typename T,
    506          typename BinaryPredicate>
    507 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
    508    container_algorithm_internal::ContainerIter<Sequence>
    509    c_search_n(Sequence& sequence, Size count, T&& value,
    510               BinaryPredicate&& pred) {
    511  return std::search_n(container_algorithm_internal::c_begin(sequence),
    512                       container_algorithm_internal::c_end(sequence), count,
    513                       std::forward<T>(value),
    514                       std::forward<BinaryPredicate>(pred));
    515 }
    516 
    517 //------------------------------------------------------------------------------
    518 // <algorithm> Modifying sequence operations
    519 //------------------------------------------------------------------------------
    520 
    521 // c_copy()
    522 //
    523 // Container-based version of the <algorithm> `std::copy()` function to copy a
    524 // container's elements into an iterator.
    525 template <typename InputSequence, typename OutputIterator>
    526 OutputIterator c_copy(const InputSequence& input, OutputIterator output) {
    527  return std::copy(container_algorithm_internal::c_begin(input),
    528                   container_algorithm_internal::c_end(input), output);
    529 }
    530 
    531 // c_copy_n()
    532 //
    533 // Container-based version of the <algorithm> `std::copy_n()` function to copy a
    534 // container's first N elements into an iterator.
    535 template <typename C, typename Size, typename OutputIterator>
    536 OutputIterator c_copy_n(const C& input, Size n, OutputIterator output) {
    537  return std::copy_n(container_algorithm_internal::c_begin(input), n, output);
    538 }
    539 
    540 // c_copy_if()
    541 //
    542 // Container-based version of the <algorithm> `std::copy_if()` function to copy
    543 // a container's elements satisfying some condition into an iterator.
    544 template <typename InputSequence, typename OutputIterator, typename Pred>
    545 OutputIterator c_copy_if(const InputSequence& input, OutputIterator output,
    546                         Pred&& pred) {
    547  return std::copy_if(container_algorithm_internal::c_begin(input),
    548                      container_algorithm_internal::c_end(input), output,
    549                      std::forward<Pred>(pred));
    550 }
    551 
    552 // c_copy_backward()
    553 //
    554 // Container-based version of the <algorithm> `std::copy_backward()` function to
    555 // copy a container's elements in reverse order into an iterator.
    556 template <typename C, typename BidirectionalIterator>
    557 BidirectionalIterator c_copy_backward(const C& src,
    558                                      BidirectionalIterator dest) {
    559  return std::copy_backward(container_algorithm_internal::c_begin(src),
    560                            container_algorithm_internal::c_end(src), dest);
    561 }
    562 
    563 // c_move()
    564 //
    565 // Container-based version of the <algorithm> `std::move()` function to move
    566 // a container's elements into an iterator.
    567 template <typename C, typename OutputIterator>
    568 OutputIterator c_move(C&& src, OutputIterator dest) {
    569  return std::move(container_algorithm_internal::c_begin(src),
    570                   container_algorithm_internal::c_end(src), dest);
    571 }
    572 
    573 // c_move_backward()
    574 //
    575 // Container-based version of the <algorithm> `std::move_backward()` function to
    576 // move a container's elements into an iterator in reverse order.
    577 template <typename C, typename BidirectionalIterator>
    578 BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator dest) {
    579  return std::move_backward(container_algorithm_internal::c_begin(src),
    580                            container_algorithm_internal::c_end(src), dest);
    581 }
    582 
    583 // c_swap_ranges()
    584 //
    585 // Container-based version of the <algorithm> `std::swap_ranges()` function to
    586 // swap a container's elements with another container's elements. Swaps the
    587 // first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
    588 template <typename C1, typename C2>
    589 container_algorithm_internal::ContainerIter<C2> c_swap_ranges(C1& c1, C2& c2) {
    590  auto first1 = container_algorithm_internal::c_begin(c1);
    591  auto last1 = container_algorithm_internal::c_end(c1);
    592  auto first2 = container_algorithm_internal::c_begin(c2);
    593  auto last2 = container_algorithm_internal::c_end(c2);
    594 
    595  using std::swap;
    596  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
    597    swap(*first1, *first2);
    598  }
    599  return first2;
    600 }
    601 
    602 // c_transform()
    603 //
    604 // Container-based version of the <algorithm> `std::transform()` function to
    605 // transform a container's elements using the unary operation, storing the
    606 // result in an iterator pointing to the last transformed element in the output
    607 // range.
    608 template <typename InputSequence, typename OutputIterator, typename UnaryOp>
    609 OutputIterator c_transform(const InputSequence& input, OutputIterator output,
    610                           UnaryOp&& unary_op) {
    611  return std::transform(container_algorithm_internal::c_begin(input),
    612                        container_algorithm_internal::c_end(input), output,
    613                        std::forward<UnaryOp>(unary_op));
    614 }
    615 
    616 // Overload of c_transform() for performing a transformation using a binary
    617 // predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,
    618 // where N = min(size(c1), size(c2)).
    619 template <typename InputSequence1, typename InputSequence2,
    620          typename OutputIterator, typename BinaryOp>
    621 OutputIterator c_transform(const InputSequence1& input1,
    622                           const InputSequence2& input2, OutputIterator output,
    623                           BinaryOp&& binary_op) {
    624  auto first1 = container_algorithm_internal::c_begin(input1);
    625  auto last1 = container_algorithm_internal::c_end(input1);
    626  auto first2 = container_algorithm_internal::c_begin(input2);
    627  auto last2 = container_algorithm_internal::c_end(input2);
    628  for (; first1 != last1 && first2 != last2;
    629       ++first1, (void)++first2, ++output) {
    630    *output = binary_op(*first1, *first2);
    631  }
    632 
    633  return output;
    634 }
    635 
    636 // c_replace()
    637 //
    638 // Container-based version of the <algorithm> `std::replace()` function to
    639 // replace a container's elements of some value with a new value. The container
    640 // is modified in place.
    641 template <typename Sequence, typename T>
    642 void c_replace(Sequence& sequence, const T& old_value, const T& new_value) {
    643  std::replace(container_algorithm_internal::c_begin(sequence),
    644               container_algorithm_internal::c_end(sequence), old_value,
    645               new_value);
    646 }
    647 
    648 // c_replace_if()
    649 //
    650 // Container-based version of the <algorithm> `std::replace_if()` function to
    651 // replace a container's elements of some value with a new value based on some
    652 // condition. The container is modified in place.
    653 template <typename C, typename Pred, typename T>
    654 void c_replace_if(C& c, Pred&& pred, T&& new_value) {
    655  std::replace_if(container_algorithm_internal::c_begin(c),
    656                  container_algorithm_internal::c_end(c),
    657                  std::forward<Pred>(pred), std::forward<T>(new_value));
    658 }
    659 
    660 // c_replace_copy()
    661 //
    662 // Container-based version of the <algorithm> `std::replace_copy()` function to
    663 // replace a container's elements of some value with a new value  and return the
    664 // results within an iterator.
    665 template <typename C, typename OutputIterator, typename T>
    666 OutputIterator c_replace_copy(const C& c, OutputIterator result, T&& old_value,
    667                              T&& new_value) {
    668  return std::replace_copy(container_algorithm_internal::c_begin(c),
    669                           container_algorithm_internal::c_end(c), result,
    670                           std::forward<T>(old_value),
    671                           std::forward<T>(new_value));
    672 }
    673 
    674 // c_replace_copy_if()
    675 //
    676 // Container-based version of the <algorithm> `std::replace_copy_if()` function
    677 // to replace a container's elements of some value with a new value based on
    678 // some condition, and return the results within an iterator.
    679 template <typename C, typename OutputIterator, typename Pred, typename T>
    680 OutputIterator c_replace_copy_if(const C& c, OutputIterator result, Pred&& pred,
    681                                 const T& new_value) {
    682  return std::replace_copy_if(container_algorithm_internal::c_begin(c),
    683                              container_algorithm_internal::c_end(c), result,
    684                              std::forward<Pred>(pred), new_value);
    685 }
    686 
    687 // c_fill()
    688 //
    689 // Container-based version of the <algorithm> `std::fill()` function to fill a
    690 // container with some value.
    691 template <typename C, typename T>
    692 void c_fill(C& c, const T& value) {
    693  std::fill(container_algorithm_internal::c_begin(c),
    694            container_algorithm_internal::c_end(c), value);
    695 }
    696 
    697 // c_fill_n()
    698 //
    699 // Container-based version of the <algorithm> `std::fill_n()` function to fill
    700 // the first N elements in a container with some value.
    701 template <typename C, typename Size, typename T>
    702 void c_fill_n(C& c, Size n, const T& value) {
    703  std::fill_n(container_algorithm_internal::c_begin(c), n, value);
    704 }
    705 
    706 // c_generate()
    707 //
    708 // Container-based version of the <algorithm> `std::generate()` function to
    709 // assign a container's elements to the values provided by the given generator.
    710 template <typename C, typename Generator>
    711 void c_generate(C& c, Generator&& gen) {
    712  std::generate(container_algorithm_internal::c_begin(c),
    713                container_algorithm_internal::c_end(c),
    714                std::forward<Generator>(gen));
    715 }
    716 
    717 // c_generate_n()
    718 //
    719 // Container-based version of the <algorithm> `std::generate_n()` function to
    720 // assign a container's first N elements to the values provided by the given
    721 // generator.
    722 template <typename C, typename Size, typename Generator>
    723 container_algorithm_internal::ContainerIter<C> c_generate_n(C& c, Size n,
    724                                                            Generator&& gen) {
    725  return std::generate_n(container_algorithm_internal::c_begin(c), n,
    726                         std::forward<Generator>(gen));
    727 }
    728 
    729 // Note: `c_xx()` <algorithm> container versions for `remove()`, `remove_if()`,
    730 // and `unique()` are omitted, because it's not clear whether or not such
    731 // functions should call erase on their supplied sequences afterwards. Either
    732 // behavior would be surprising for a different set of users.
    733 
    734 // c_remove_copy()
    735 //
    736 // Container-based version of the <algorithm> `std::remove_copy()` function to
    737 // copy a container's elements while removing any elements matching the given
    738 // `value`.
    739 template <typename C, typename OutputIterator, typename T>
    740 OutputIterator c_remove_copy(const C& c, OutputIterator result,
    741                             const T& value) {
    742  return std::remove_copy(container_algorithm_internal::c_begin(c),
    743                          container_algorithm_internal::c_end(c), result,
    744                          value);
    745 }
    746 
    747 // c_remove_copy_if()
    748 //
    749 // Container-based version of the <algorithm> `std::remove_copy_if()` function
    750 // to copy a container's elements while removing any elements matching the given
    751 // condition.
    752 template <typename C, typename OutputIterator, typename Pred>
    753 OutputIterator c_remove_copy_if(const C& c, OutputIterator result,
    754                                Pred&& pred) {
    755  return std::remove_copy_if(container_algorithm_internal::c_begin(c),
    756                             container_algorithm_internal::c_end(c), result,
    757                             std::forward<Pred>(pred));
    758 }
    759 
    760 // c_unique_copy()
    761 //
    762 // Container-based version of the <algorithm> `std::unique_copy()` function to
    763 // copy a container's elements while removing any elements containing duplicate
    764 // values.
    765 template <typename C, typename OutputIterator>
    766 OutputIterator c_unique_copy(const C& c, OutputIterator result) {
    767  return std::unique_copy(container_algorithm_internal::c_begin(c),
    768                          container_algorithm_internal::c_end(c), result);
    769 }
    770 
    771 // Overload of c_unique_copy() for using a predicate evaluation other than
    772 // `==` for comparing uniqueness of the element values.
    773 template <typename C, typename OutputIterator, typename BinaryPredicate>
    774 OutputIterator c_unique_copy(const C& c, OutputIterator result,
    775                             BinaryPredicate&& pred) {
    776  return std::unique_copy(container_algorithm_internal::c_begin(c),
    777                          container_algorithm_internal::c_end(c), result,
    778                          std::forward<BinaryPredicate>(pred));
    779 }
    780 
    781 // c_reverse()
    782 //
    783 // Container-based version of the <algorithm> `std::reverse()` function to
    784 // reverse a container's elements.
    785 template <typename Sequence>
    786 void c_reverse(Sequence& sequence) {
    787  std::reverse(container_algorithm_internal::c_begin(sequence),
    788               container_algorithm_internal::c_end(sequence));
    789 }
    790 
    791 // c_reverse_copy()
    792 //
    793 // Container-based version of the <algorithm> `std::reverse()` function to
    794 // reverse a container's elements and write them to an iterator range.
    795 template <typename C, typename OutputIterator>
    796 OutputIterator c_reverse_copy(const C& sequence, OutputIterator result) {
    797  return std::reverse_copy(container_algorithm_internal::c_begin(sequence),
    798                           container_algorithm_internal::c_end(sequence),
    799                           result);
    800 }
    801 
    802 // c_rotate()
    803 //
    804 // Container-based version of the <algorithm> `std::rotate()` function to
    805 // shift a container's elements leftward such that the `middle` element becomes
    806 // the first element in the container.
    807 template <typename C,
    808          typename Iterator = container_algorithm_internal::ContainerIter<C>>
    809 Iterator c_rotate(C& sequence, Iterator middle) {
    810  return absl::rotate(container_algorithm_internal::c_begin(sequence), middle,
    811                      container_algorithm_internal::c_end(sequence));
    812 }
    813 
    814 // c_rotate_copy()
    815 //
    816 // Container-based version of the <algorithm> `std::rotate_copy()` function to
    817 // shift a container's elements leftward such that the `middle` element becomes
    818 // the first element in a new iterator range.
    819 template <typename C, typename OutputIterator>
    820 OutputIterator c_rotate_copy(
    821    const C& sequence,
    822    container_algorithm_internal::ContainerIter<const C> middle,
    823    OutputIterator result) {
    824  return std::rotate_copy(container_algorithm_internal::c_begin(sequence),
    825                          middle, container_algorithm_internal::c_end(sequence),
    826                          result);
    827 }
    828 
    829 // c_shuffle()
    830 //
    831 // Container-based version of the <algorithm> `std::shuffle()` function to
    832 // randomly shuffle elements within the container using a `gen()` uniform random
    833 // number generator.
    834 template <typename RandomAccessContainer, typename UniformRandomBitGenerator>
    835 void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) {
    836  std::shuffle(container_algorithm_internal::c_begin(c),
    837               container_algorithm_internal::c_end(c),
    838               std::forward<UniformRandomBitGenerator>(gen));
    839 }
    840 
    841 // c_sample()
    842 //
    843 // Container-based version of the <algorithm> `std::sample()` function to
    844 // randomly sample elements from the container without replacement using a
    845 // `gen()` uniform random number generator and write them to an iterator range.
    846 template <typename C, typename OutputIterator, typename Distance,
    847          typename UniformRandomBitGenerator>
    848 OutputIterator c_sample(const C& c, OutputIterator result, Distance n,
    849                        UniformRandomBitGenerator&& gen) {
    850 #if defined(__cpp_lib_sample) && __cpp_lib_sample >= 201603L
    851  return std::sample(container_algorithm_internal::c_begin(c),
    852                     container_algorithm_internal::c_end(c), result, n,
    853                     std::forward<UniformRandomBitGenerator>(gen));
    854 #else
    855  // Fall back to a stable selection-sampling implementation.
    856  auto first = container_algorithm_internal::c_begin(c);
    857  Distance unsampled_elements = c_distance(c);
    858  n = (std::min)(n, unsampled_elements);
    859  for (; n != 0; ++first) {
    860    Distance r =
    861        std::uniform_int_distribution<Distance>(0, --unsampled_elements)(gen);
    862    if (r < n) {
    863      *result++ = *first;
    864      --n;
    865    }
    866  }
    867  return result;
    868 #endif
    869 }
    870 
    871 //------------------------------------------------------------------------------
    872 // <algorithm> Partition functions
    873 //------------------------------------------------------------------------------
    874 
    875 // c_is_partitioned()
    876 //
    877 // Container-based version of the <algorithm> `std::is_partitioned()` function
    878 // to test whether all elements in the container for which `pred` returns `true`
    879 // precede those for which `pred` is `false`.
    880 template <typename C, typename Pred>
    881 bool c_is_partitioned(const C& c, Pred&& pred) {
    882  return std::is_partitioned(container_algorithm_internal::c_begin(c),
    883                             container_algorithm_internal::c_end(c),
    884                             std::forward<Pred>(pred));
    885 }
    886 
    887 // c_partition()
    888 //
    889 // Container-based version of the <algorithm> `std::partition()` function
    890 // to rearrange all elements in a container in such a way that all elements for
    891 // which `pred` returns `true` precede all those for which it returns `false`,
    892 // returning an iterator to the first element of the second group.
    893 template <typename C, typename Pred>
    894 container_algorithm_internal::ContainerIter<C> c_partition(C& c, Pred&& pred) {
    895  return std::partition(container_algorithm_internal::c_begin(c),
    896                        container_algorithm_internal::c_end(c),
    897                        std::forward<Pred>(pred));
    898 }
    899 
    900 // c_stable_partition()
    901 //
    902 // Container-based version of the <algorithm> `std::stable_partition()` function
    903 // to rearrange all elements in a container in such a way that all elements for
    904 // which `pred` returns `true` precede all those for which it returns `false`,
    905 // preserving the relative ordering between the two groups. The function returns
    906 // an iterator to the first element of the second group.
    907 template <typename C, typename Pred>
    908 container_algorithm_internal::ContainerIter<C> c_stable_partition(C& c,
    909                                                                  Pred&& pred) {
    910  return std::stable_partition(container_algorithm_internal::c_begin(c),
    911                               container_algorithm_internal::c_end(c),
    912                               std::forward<Pred>(pred));
    913 }
    914 
    915 // c_partition_copy()
    916 //
    917 // Container-based version of the <algorithm> `std::partition_copy()` function
    918 // to partition a container's elements and return them into two iterators: one
    919 // for which `pred` returns `true`, and one for which `pred` returns `false.`
    920 
    921 template <typename C, typename OutputIterator1, typename OutputIterator2,
    922          typename Pred>
    923 std::pair<OutputIterator1, OutputIterator2> c_partition_copy(
    924    const C& c, OutputIterator1 out_true, OutputIterator2 out_false,
    925    Pred&& pred) {
    926  return std::partition_copy(container_algorithm_internal::c_begin(c),
    927                             container_algorithm_internal::c_end(c), out_true,
    928                             out_false, std::forward<Pred>(pred));
    929 }
    930 
    931 // c_partition_point()
    932 //
    933 // Container-based version of the <algorithm> `std::partition_point()` function
    934 // to return the first element of an already partitioned container for which
    935 // the given `pred` is not `true`.
    936 template <typename C, typename Pred>
    937 container_algorithm_internal::ContainerIter<C> c_partition_point(C& c,
    938                                                                 Pred&& pred) {
    939  return std::partition_point(container_algorithm_internal::c_begin(c),
    940                              container_algorithm_internal::c_end(c),
    941                              std::forward<Pred>(pred));
    942 }
    943 
    944 //------------------------------------------------------------------------------
    945 // <algorithm> Sorting functions
    946 //------------------------------------------------------------------------------
    947 
    948 // c_sort()
    949 //
    950 // Container-based version of the <algorithm> `std::sort()` function
    951 // to sort elements in ascending order of their values.
    952 template <typename C>
    953 void c_sort(C& c) {
    954  std::sort(container_algorithm_internal::c_begin(c),
    955            container_algorithm_internal::c_end(c));
    956 }
    957 
    958 // Overload of c_sort() for performing a `comp` comparison other than the
    959 // default `operator<`.
    960 template <typename C, typename LessThan>
    961 void c_sort(C& c, LessThan&& comp) {
    962  std::sort(container_algorithm_internal::c_begin(c),
    963            container_algorithm_internal::c_end(c),
    964            std::forward<LessThan>(comp));
    965 }
    966 
    967 // c_stable_sort()
    968 //
    969 // Container-based version of the <algorithm> `std::stable_sort()` function
    970 // to sort elements in ascending order of their values, preserving the order
    971 // of equivalents.
    972 template <typename C>
    973 void c_stable_sort(C& c) {
    974  std::stable_sort(container_algorithm_internal::c_begin(c),
    975                   container_algorithm_internal::c_end(c));
    976 }
    977 
    978 // Overload of c_stable_sort() for performing a `comp` comparison other than the
    979 // default `operator<`.
    980 template <typename C, typename LessThan>
    981 void c_stable_sort(C& c, LessThan&& comp) {
    982  std::stable_sort(container_algorithm_internal::c_begin(c),
    983                   container_algorithm_internal::c_end(c),
    984                   std::forward<LessThan>(comp));
    985 }
    986 
    987 // c_is_sorted()
    988 //
    989 // Container-based version of the <algorithm> `std::is_sorted()` function
    990 // to evaluate whether the given container is sorted in ascending order.
    991 template <typename C>
    992 bool c_is_sorted(const C& c) {
    993  return std::is_sorted(container_algorithm_internal::c_begin(c),
    994                        container_algorithm_internal::c_end(c));
    995 }
    996 
    997 // c_is_sorted() overload for performing a `comp` comparison other than the
    998 // default `operator<`.
    999 template <typename C, typename LessThan>
   1000 bool c_is_sorted(const C& c, LessThan&& comp) {
   1001  return std::is_sorted(container_algorithm_internal::c_begin(c),
   1002                        container_algorithm_internal::c_end(c),
   1003                        std::forward<LessThan>(comp));
   1004 }
   1005 
   1006 // c_partial_sort()
   1007 //
   1008 // Container-based version of the <algorithm> `std::partial_sort()` function
   1009 // to rearrange elements within a container such that elements before `middle`
   1010 // are sorted in ascending order.
   1011 template <typename RandomAccessContainer>
   1012 void c_partial_sort(
   1013    RandomAccessContainer& sequence,
   1014    container_algorithm_internal::ContainerIter<RandomAccessContainer> middle) {
   1015  std::partial_sort(container_algorithm_internal::c_begin(sequence), middle,
   1016                    container_algorithm_internal::c_end(sequence));
   1017 }
   1018 
   1019 // Overload of c_partial_sort() for performing a `comp` comparison other than
   1020 // the default `operator<`.
   1021 template <typename RandomAccessContainer, typename LessThan>
   1022 void c_partial_sort(
   1023    RandomAccessContainer& sequence,
   1024    container_algorithm_internal::ContainerIter<RandomAccessContainer> middle,
   1025    LessThan&& comp) {
   1026  std::partial_sort(container_algorithm_internal::c_begin(sequence), middle,
   1027                    container_algorithm_internal::c_end(sequence),
   1028                    std::forward<LessThan>(comp));
   1029 }
   1030 
   1031 // c_partial_sort_copy()
   1032 //
   1033 // Container-based version of the <algorithm> `std::partial_sort_copy()`
   1034 // function to sort the elements in the given range `result` within the larger
   1035 // `sequence` in ascending order (and using `result` as the output parameter).
   1036 // At most min(result.last - result.first, sequence.last - sequence.first)
   1037 // elements from the sequence will be stored in the result.
   1038 template <typename C, typename RandomAccessContainer>
   1039 container_algorithm_internal::ContainerIter<RandomAccessContainer>
   1040 c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {
   1041  return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence),
   1042                                container_algorithm_internal::c_end(sequence),
   1043                                container_algorithm_internal::c_begin(result),
   1044                                container_algorithm_internal::c_end(result));
   1045 }
   1046 
   1047 // Overload of c_partial_sort_copy() for performing a `comp` comparison other
   1048 // than the default `operator<`.
   1049 template <typename C, typename RandomAccessContainer, typename LessThan>
   1050 container_algorithm_internal::ContainerIter<RandomAccessContainer>
   1051 c_partial_sort_copy(const C& sequence, RandomAccessContainer& result,
   1052                    LessThan&& comp) {
   1053  return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence),
   1054                                container_algorithm_internal::c_end(sequence),
   1055                                container_algorithm_internal::c_begin(result),
   1056                                container_algorithm_internal::c_end(result),
   1057                                std::forward<LessThan>(comp));
   1058 }
   1059 
   1060 // c_is_sorted_until()
   1061 //
   1062 // Container-based version of the <algorithm> `std::is_sorted_until()` function
   1063 // to return the first element within a container that is not sorted in
   1064 // ascending order as an iterator.
   1065 template <typename C>
   1066 container_algorithm_internal::ContainerIter<C> c_is_sorted_until(C& c) {
   1067  return std::is_sorted_until(container_algorithm_internal::c_begin(c),
   1068                              container_algorithm_internal::c_end(c));
   1069 }
   1070 
   1071 // Overload of c_is_sorted_until() for performing a `comp` comparison other than
   1072 // the default `operator<`.
   1073 template <typename C, typename LessThan>
   1074 container_algorithm_internal::ContainerIter<C> c_is_sorted_until(
   1075    C& c, LessThan&& comp) {
   1076  return std::is_sorted_until(container_algorithm_internal::c_begin(c),
   1077                              container_algorithm_internal::c_end(c),
   1078                              std::forward<LessThan>(comp));
   1079 }
   1080 
   1081 // c_nth_element()
   1082 //
   1083 // Container-based version of the <algorithm> `std::nth_element()` function
   1084 // to rearrange the elements within a container such that the `nth` element
   1085 // would be in that position in an ordered sequence; other elements may be in
   1086 // any order, except that all preceding `nth` will be less than that element,
   1087 // and all following `nth` will be greater than that element.
   1088 template <typename RandomAccessContainer>
   1089 void c_nth_element(
   1090    RandomAccessContainer& sequence,
   1091    container_algorithm_internal::ContainerIter<RandomAccessContainer> nth) {
   1092  std::nth_element(container_algorithm_internal::c_begin(sequence), nth,
   1093                   container_algorithm_internal::c_end(sequence));
   1094 }
   1095 
   1096 // Overload of c_nth_element() for performing a `comp` comparison other than
   1097 // the default `operator<`.
   1098 template <typename RandomAccessContainer, typename LessThan>
   1099 void c_nth_element(
   1100    RandomAccessContainer& sequence,
   1101    container_algorithm_internal::ContainerIter<RandomAccessContainer> nth,
   1102    LessThan&& comp) {
   1103  std::nth_element(container_algorithm_internal::c_begin(sequence), nth,
   1104                   container_algorithm_internal::c_end(sequence),
   1105                   std::forward<LessThan>(comp));
   1106 }
   1107 
   1108 //------------------------------------------------------------------------------
   1109 // <algorithm> Binary Search
   1110 //------------------------------------------------------------------------------
   1111 
   1112 // c_lower_bound()
   1113 //
   1114 // Container-based version of the <algorithm> `std::lower_bound()` function
   1115 // to return an iterator pointing to the first element in a sorted container
   1116 // which does not compare less than `value`.
   1117 template <typename Sequence, typename T>
   1118 container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
   1119    Sequence& sequence, const T& value) {
   1120  return std::lower_bound(container_algorithm_internal::c_begin(sequence),
   1121                          container_algorithm_internal::c_end(sequence), value);
   1122 }
   1123 
   1124 // Overload of c_lower_bound() for performing a `comp` comparison other than
   1125 // the default `operator<`.
   1126 template <typename Sequence, typename T, typename LessThan>
   1127 container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
   1128    Sequence& sequence, const T& value, LessThan&& comp) {
   1129  return std::lower_bound(container_algorithm_internal::c_begin(sequence),
   1130                          container_algorithm_internal::c_end(sequence), value,
   1131                          std::forward<LessThan>(comp));
   1132 }
   1133 
   1134 // c_upper_bound()
   1135 //
   1136 // Container-based version of the <algorithm> `std::upper_bound()` function
   1137 // to return an iterator pointing to the first element in a sorted container
   1138 // which is greater than `value`.
   1139 template <typename Sequence, typename T>
   1140 container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
   1141    Sequence& sequence, const T& value) {
   1142  return std::upper_bound(container_algorithm_internal::c_begin(sequence),
   1143                          container_algorithm_internal::c_end(sequence), value);
   1144 }
   1145 
   1146 // Overload of c_upper_bound() for performing a `comp` comparison other than
   1147 // the default `operator<`.
   1148 template <typename Sequence, typename T, typename LessThan>
   1149 container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
   1150    Sequence& sequence, const T& value, LessThan&& comp) {
   1151  return std::upper_bound(container_algorithm_internal::c_begin(sequence),
   1152                          container_algorithm_internal::c_end(sequence), value,
   1153                          std::forward<LessThan>(comp));
   1154 }
   1155 
   1156 // c_equal_range()
   1157 //
   1158 // Container-based version of the <algorithm> `std::equal_range()` function
   1159 // to return an iterator pair pointing to the first and last elements in a
   1160 // sorted container which compare equal to `value`.
   1161 template <typename Sequence, typename T>
   1162 container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
   1163 c_equal_range(Sequence& sequence, const T& value) {
   1164  return std::equal_range(container_algorithm_internal::c_begin(sequence),
   1165                          container_algorithm_internal::c_end(sequence), value);
   1166 }
   1167 
   1168 // Overload of c_equal_range() for performing a `comp` comparison other than
   1169 // the default `operator<`.
   1170 template <typename Sequence, typename T, typename LessThan>
   1171 container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
   1172 c_equal_range(Sequence& sequence, const T& value, LessThan&& comp) {
   1173  return std::equal_range(container_algorithm_internal::c_begin(sequence),
   1174                          container_algorithm_internal::c_end(sequence), value,
   1175                          std::forward<LessThan>(comp));
   1176 }
   1177 
   1178 // c_binary_search()
   1179 //
   1180 // Container-based version of the <algorithm> `std::binary_search()` function
   1181 // to test if any element in the sorted container contains a value equivalent to
   1182 // 'value'.
   1183 template <typename Sequence, typename T>
   1184 bool c_binary_search(const Sequence& sequence, const T& value) {
   1185  return std::binary_search(container_algorithm_internal::c_begin(sequence),
   1186                            container_algorithm_internal::c_end(sequence),
   1187                            value);
   1188 }
   1189 
   1190 // Overload of c_binary_search() for performing a `comp` comparison other than
   1191 // the default `operator<`.
   1192 template <typename Sequence, typename T, typename LessThan>
   1193 bool c_binary_search(const Sequence& sequence, const T& value,
   1194                     LessThan&& comp) {
   1195  return std::binary_search(container_algorithm_internal::c_begin(sequence),
   1196                            container_algorithm_internal::c_end(sequence),
   1197                            value, std::forward<LessThan>(comp));
   1198 }
   1199 
   1200 //------------------------------------------------------------------------------
   1201 // <algorithm> Merge functions
   1202 //------------------------------------------------------------------------------
   1203 
   1204 // c_merge()
   1205 //
   1206 // Container-based version of the <algorithm> `std::merge()` function
   1207 // to merge two sorted containers into a single sorted iterator.
   1208 template <typename C1, typename C2, typename OutputIterator>
   1209 OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result) {
   1210  return std::merge(container_algorithm_internal::c_begin(c1),
   1211                    container_algorithm_internal::c_end(c1),
   1212                    container_algorithm_internal::c_begin(c2),
   1213                    container_algorithm_internal::c_end(c2), result);
   1214 }
   1215 
   1216 // Overload of c_merge() for performing a `comp` comparison other than
   1217 // the default `operator<`.
   1218 template <typename C1, typename C2, typename OutputIterator, typename LessThan>
   1219 OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result,
   1220                       LessThan&& comp) {
   1221  return std::merge(container_algorithm_internal::c_begin(c1),
   1222                    container_algorithm_internal::c_end(c1),
   1223                    container_algorithm_internal::c_begin(c2),
   1224                    container_algorithm_internal::c_end(c2), result,
   1225                    std::forward<LessThan>(comp));
   1226 }
   1227 
   1228 // c_inplace_merge()
   1229 //
   1230 // Container-based version of the <algorithm> `std::inplace_merge()` function
   1231 // to merge a supplied iterator `middle` into a container.
   1232 template <typename C>
   1233 void c_inplace_merge(C& c,
   1234                     container_algorithm_internal::ContainerIter<C> middle) {
   1235  std::inplace_merge(container_algorithm_internal::c_begin(c), middle,
   1236                     container_algorithm_internal::c_end(c));
   1237 }
   1238 
   1239 // Overload of c_inplace_merge() for performing a merge using a `comp` other
   1240 // than `operator<`.
   1241 template <typename C, typename LessThan>
   1242 void c_inplace_merge(C& c,
   1243                     container_algorithm_internal::ContainerIter<C> middle,
   1244                     LessThan&& comp) {
   1245  std::inplace_merge(container_algorithm_internal::c_begin(c), middle,
   1246                     container_algorithm_internal::c_end(c),
   1247                     std::forward<LessThan>(comp));
   1248 }
   1249 
   1250 // c_includes()
   1251 //
   1252 // Container-based version of the <algorithm> `std::includes()` function
   1253 // to test whether a sorted container `c1` entirely contains another sorted
   1254 // container `c2`.
   1255 template <typename C1, typename C2>
   1256 bool c_includes(const C1& c1, const C2& c2) {
   1257  return std::includes(container_algorithm_internal::c_begin(c1),
   1258                       container_algorithm_internal::c_end(c1),
   1259                       container_algorithm_internal::c_begin(c2),
   1260                       container_algorithm_internal::c_end(c2));
   1261 }
   1262 
   1263 // Overload of c_includes() for performing a merge using a `comp` other than
   1264 // `operator<`.
   1265 template <typename C1, typename C2, typename LessThan>
   1266 bool c_includes(const C1& c1, const C2& c2, LessThan&& comp) {
   1267  return std::includes(container_algorithm_internal::c_begin(c1),
   1268                       container_algorithm_internal::c_end(c1),
   1269                       container_algorithm_internal::c_begin(c2),
   1270                       container_algorithm_internal::c_end(c2),
   1271                       std::forward<LessThan>(comp));
   1272 }
   1273 
   1274 // c_set_union()
   1275 //
   1276 // Container-based version of the <algorithm> `std::set_union()` function
   1277 // to return an iterator containing the union of two containers; duplicate
   1278 // values are not copied into the output.
   1279 template <typename C1, typename C2, typename OutputIterator,
   1280          typename = typename std::enable_if<
   1281              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
   1282              void>::type,
   1283          typename = typename std::enable_if<
   1284              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
   1285              void>::type>
   1286 OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) {
   1287  return std::set_union(container_algorithm_internal::c_begin(c1),
   1288                        container_algorithm_internal::c_end(c1),
   1289                        container_algorithm_internal::c_begin(c2),
   1290                        container_algorithm_internal::c_end(c2), output);
   1291 }
   1292 
   1293 // Overload of c_set_union() for performing a merge using a `comp` other than
   1294 // `operator<`.
   1295 template <typename C1, typename C2, typename OutputIterator, typename LessThan,
   1296          typename = typename std::enable_if<
   1297              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
   1298              void>::type,
   1299          typename = typename std::enable_if<
   1300              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
   1301              void>::type>
   1302 OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output,
   1303                           LessThan&& comp) {
   1304  return std::set_union(container_algorithm_internal::c_begin(c1),
   1305                        container_algorithm_internal::c_end(c1),
   1306                        container_algorithm_internal::c_begin(c2),
   1307                        container_algorithm_internal::c_end(c2), output,
   1308                        std::forward<LessThan>(comp));
   1309 }
   1310 
   1311 // c_set_intersection()
   1312 //
   1313 // Container-based version of the <algorithm> `std::set_intersection()` function
   1314 // to return an iterator containing the intersection of two sorted containers.
   1315 template <typename C1, typename C2, typename OutputIterator,
   1316          typename = typename std::enable_if<
   1317              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
   1318              void>::type,
   1319          typename = typename std::enable_if<
   1320              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
   1321              void>::type>
   1322 OutputIterator c_set_intersection(const C1& c1, const C2& c2,
   1323                                  OutputIterator output) {
   1324  // In debug builds, ensure that both containers are sorted with respect to the
   1325  // default comparator. std::set_intersection requires the containers be sorted
   1326  // using operator<.
   1327  assert(absl::c_is_sorted(c1));
   1328  assert(absl::c_is_sorted(c2));
   1329  return std::set_intersection(container_algorithm_internal::c_begin(c1),
   1330                               container_algorithm_internal::c_end(c1),
   1331                               container_algorithm_internal::c_begin(c2),
   1332                               container_algorithm_internal::c_end(c2), output);
   1333 }
   1334 
   1335 // Overload of c_set_intersection() for performing a merge using a `comp` other
   1336 // than `operator<`.
   1337 template <typename C1, typename C2, typename OutputIterator, typename LessThan,
   1338          typename = typename std::enable_if<
   1339              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
   1340              void>::type,
   1341          typename = typename std::enable_if<
   1342              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
   1343              void>::type>
   1344 OutputIterator c_set_intersection(const C1& c1, const C2& c2,
   1345                                  OutputIterator output, LessThan&& comp) {
   1346  // In debug builds, ensure that both containers are sorted with respect to the
   1347  // default comparator. std::set_intersection requires the containers be sorted
   1348  // using the same comparator.
   1349  assert(absl::c_is_sorted(c1, comp));
   1350  assert(absl::c_is_sorted(c2, comp));
   1351  return std::set_intersection(container_algorithm_internal::c_begin(c1),
   1352                               container_algorithm_internal::c_end(c1),
   1353                               container_algorithm_internal::c_begin(c2),
   1354                               container_algorithm_internal::c_end(c2), output,
   1355                               std::forward<LessThan>(comp));
   1356 }
   1357 
   1358 // c_set_difference()
   1359 //
   1360 // Container-based version of the <algorithm> `std::set_difference()` function
   1361 // to return an iterator containing elements present in the first container but
   1362 // not in the second.
   1363 template <typename C1, typename C2, typename OutputIterator,
   1364          typename = typename std::enable_if<
   1365              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
   1366              void>::type,
   1367          typename = typename std::enable_if<
   1368              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
   1369              void>::type>
   1370 OutputIterator c_set_difference(const C1& c1, const C2& c2,
   1371                                OutputIterator output) {
   1372  return std::set_difference(container_algorithm_internal::c_begin(c1),
   1373                             container_algorithm_internal::c_end(c1),
   1374                             container_algorithm_internal::c_begin(c2),
   1375                             container_algorithm_internal::c_end(c2), output);
   1376 }
   1377 
   1378 // Overload of c_set_difference() for performing a merge using a `comp` other
   1379 // than `operator<`.
   1380 template <typename C1, typename C2, typename OutputIterator, typename LessThan,
   1381          typename = typename std::enable_if<
   1382              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
   1383              void>::type,
   1384          typename = typename std::enable_if<
   1385              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
   1386              void>::type>
   1387 OutputIterator c_set_difference(const C1& c1, const C2& c2,
   1388                                OutputIterator output, LessThan&& comp) {
   1389  return std::set_difference(container_algorithm_internal::c_begin(c1),
   1390                             container_algorithm_internal::c_end(c1),
   1391                             container_algorithm_internal::c_begin(c2),
   1392                             container_algorithm_internal::c_end(c2), output,
   1393                             std::forward<LessThan>(comp));
   1394 }
   1395 
   1396 // c_set_symmetric_difference()
   1397 //
   1398 // Container-based version of the <algorithm> `std::set_symmetric_difference()`
   1399 // function to return an iterator containing elements present in either one
   1400 // container or the other, but not both.
   1401 template <typename C1, typename C2, typename OutputIterator,
   1402          typename = typename std::enable_if<
   1403              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
   1404              void>::type,
   1405          typename = typename std::enable_if<
   1406              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
   1407              void>::type>
   1408 OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
   1409                                          OutputIterator output) {
   1410  return std::set_symmetric_difference(
   1411      container_algorithm_internal::c_begin(c1),
   1412      container_algorithm_internal::c_end(c1),
   1413      container_algorithm_internal::c_begin(c2),
   1414      container_algorithm_internal::c_end(c2), output);
   1415 }
   1416 
   1417 // Overload of c_set_symmetric_difference() for performing a merge using a
   1418 // `comp` other than `operator<`.
   1419 template <typename C1, typename C2, typename OutputIterator, typename LessThan,
   1420          typename = typename std::enable_if<
   1421              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
   1422              void>::type,
   1423          typename = typename std::enable_if<
   1424              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
   1425              void>::type>
   1426 OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
   1427                                          OutputIterator output,
   1428                                          LessThan&& comp) {
   1429  return std::set_symmetric_difference(
   1430      container_algorithm_internal::c_begin(c1),
   1431      container_algorithm_internal::c_end(c1),
   1432      container_algorithm_internal::c_begin(c2),
   1433      container_algorithm_internal::c_end(c2), output,
   1434      std::forward<LessThan>(comp));
   1435 }
   1436 
   1437 //------------------------------------------------------------------------------
   1438 // <algorithm> Heap functions
   1439 //------------------------------------------------------------------------------
   1440 
   1441 // c_push_heap()
   1442 //
   1443 // Container-based version of the <algorithm> `std::push_heap()` function
   1444 // to push a value onto a container heap.
   1445 template <typename RandomAccessContainer>
   1446 void c_push_heap(RandomAccessContainer& sequence) {
   1447  std::push_heap(container_algorithm_internal::c_begin(sequence),
   1448                 container_algorithm_internal::c_end(sequence));
   1449 }
   1450 
   1451 // Overload of c_push_heap() for performing a push operation on a heap using a
   1452 // `comp` other than `operator<`.
   1453 template <typename RandomAccessContainer, typename LessThan>
   1454 void c_push_heap(RandomAccessContainer& sequence, LessThan&& comp) {
   1455  std::push_heap(container_algorithm_internal::c_begin(sequence),
   1456                 container_algorithm_internal::c_end(sequence),
   1457                 std::forward<LessThan>(comp));
   1458 }
   1459 
   1460 // c_pop_heap()
   1461 //
   1462 // Container-based version of the <algorithm> `std::pop_heap()` function
   1463 // to pop a value from a heap container.
   1464 template <typename RandomAccessContainer>
   1465 void c_pop_heap(RandomAccessContainer& sequence) {
   1466  std::pop_heap(container_algorithm_internal::c_begin(sequence),
   1467                container_algorithm_internal::c_end(sequence));
   1468 }
   1469 
   1470 // Overload of c_pop_heap() for performing a pop operation on a heap using a
   1471 // `comp` other than `operator<`.
   1472 template <typename RandomAccessContainer, typename LessThan>
   1473 void c_pop_heap(RandomAccessContainer& sequence, LessThan&& comp) {
   1474  std::pop_heap(container_algorithm_internal::c_begin(sequence),
   1475                container_algorithm_internal::c_end(sequence),
   1476                std::forward<LessThan>(comp));
   1477 }
   1478 
   1479 // c_make_heap()
   1480 //
   1481 // Container-based version of the <algorithm> `std::make_heap()` function
   1482 // to make a container a heap.
   1483 template <typename RandomAccessContainer>
   1484 void c_make_heap(RandomAccessContainer& sequence) {
   1485  std::make_heap(container_algorithm_internal::c_begin(sequence),
   1486                 container_algorithm_internal::c_end(sequence));
   1487 }
   1488 
   1489 // Overload of c_make_heap() for performing heap comparisons using a
   1490 // `comp` other than `operator<`
   1491 template <typename RandomAccessContainer, typename LessThan>
   1492 void c_make_heap(RandomAccessContainer& sequence, LessThan&& comp) {
   1493  std::make_heap(container_algorithm_internal::c_begin(sequence),
   1494                 container_algorithm_internal::c_end(sequence),
   1495                 std::forward<LessThan>(comp));
   1496 }
   1497 
   1498 // c_sort_heap()
   1499 //
   1500 // Container-based version of the <algorithm> `std::sort_heap()` function
   1501 // to sort a heap into ascending order (after which it is no longer a heap).
   1502 template <typename RandomAccessContainer>
   1503 void c_sort_heap(RandomAccessContainer& sequence) {
   1504  std::sort_heap(container_algorithm_internal::c_begin(sequence),
   1505                 container_algorithm_internal::c_end(sequence));
   1506 }
   1507 
   1508 // Overload of c_sort_heap() for performing heap comparisons using a
   1509 // `comp` other than `operator<`
   1510 template <typename RandomAccessContainer, typename LessThan>
   1511 void c_sort_heap(RandomAccessContainer& sequence, LessThan&& comp) {
   1512  std::sort_heap(container_algorithm_internal::c_begin(sequence),
   1513                 container_algorithm_internal::c_end(sequence),
   1514                 std::forward<LessThan>(comp));
   1515 }
   1516 
   1517 // c_is_heap()
   1518 //
   1519 // Container-based version of the <algorithm> `std::is_heap()` function
   1520 // to check whether the given container is a heap.
   1521 template <typename RandomAccessContainer>
   1522 bool c_is_heap(const RandomAccessContainer& sequence) {
   1523  return std::is_heap(container_algorithm_internal::c_begin(sequence),
   1524                      container_algorithm_internal::c_end(sequence));
   1525 }
   1526 
   1527 // Overload of c_is_heap() for performing heap comparisons using a
   1528 // `comp` other than `operator<`
   1529 template <typename RandomAccessContainer, typename LessThan>
   1530 bool c_is_heap(const RandomAccessContainer& sequence, LessThan&& comp) {
   1531  return std::is_heap(container_algorithm_internal::c_begin(sequence),
   1532                      container_algorithm_internal::c_end(sequence),
   1533                      std::forward<LessThan>(comp));
   1534 }
   1535 
   1536 // c_is_heap_until()
   1537 //
   1538 // Container-based version of the <algorithm> `std::is_heap_until()` function
   1539 // to find the first element in a given container which is not in heap order.
   1540 template <typename RandomAccessContainer>
   1541 container_algorithm_internal::ContainerIter<RandomAccessContainer>
   1542 c_is_heap_until(RandomAccessContainer& sequence) {
   1543  return std::is_heap_until(container_algorithm_internal::c_begin(sequence),
   1544                            container_algorithm_internal::c_end(sequence));
   1545 }
   1546 
   1547 // Overload of c_is_heap_until() for performing heap comparisons using a
   1548 // `comp` other than `operator<`
   1549 template <typename RandomAccessContainer, typename LessThan>
   1550 container_algorithm_internal::ContainerIter<RandomAccessContainer>
   1551 c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {
   1552  return std::is_heap_until(container_algorithm_internal::c_begin(sequence),
   1553                            container_algorithm_internal::c_end(sequence),
   1554                            std::forward<LessThan>(comp));
   1555 }
   1556 
   1557 //------------------------------------------------------------------------------
   1558 //  <algorithm> Min/max
   1559 //------------------------------------------------------------------------------
   1560 
   1561 // c_min_element()
   1562 //
   1563 // Container-based version of the <algorithm> `std::min_element()` function
   1564 // to return an iterator pointing to the element with the smallest value, using
   1565 // `operator<` to make the comparisons.
   1566 template <typename Sequence>
   1567 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
   1568    container_algorithm_internal::ContainerIter<Sequence>
   1569    c_min_element(Sequence& sequence) {
   1570  return std::min_element(container_algorithm_internal::c_begin(sequence),
   1571                          container_algorithm_internal::c_end(sequence));
   1572 }
   1573 
   1574 // Overload of c_min_element() for performing a `comp` comparison other than
   1575 // `operator<`.
   1576 template <typename Sequence, typename LessThan>
   1577 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
   1578    container_algorithm_internal::ContainerIter<Sequence>
   1579    c_min_element(Sequence& sequence, LessThan&& comp) {
   1580  return std::min_element(container_algorithm_internal::c_begin(sequence),
   1581                          container_algorithm_internal::c_end(sequence),
   1582                          std::forward<LessThan>(comp));
   1583 }
   1584 
   1585 // c_max_element()
   1586 //
   1587 // Container-based version of the <algorithm> `std::max_element()` function
   1588 // to return an iterator pointing to the element with the largest value, using
   1589 // `operator<` to make the comparisons.
   1590 template <typename Sequence>
   1591 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
   1592    container_algorithm_internal::ContainerIter<Sequence>
   1593    c_max_element(Sequence& sequence) {
   1594  return std::max_element(container_algorithm_internal::c_begin(sequence),
   1595                          container_algorithm_internal::c_end(sequence));
   1596 }
   1597 
   1598 // Overload of c_max_element() for performing a `comp` comparison other than
   1599 // `operator<`.
   1600 template <typename Sequence, typename LessThan>
   1601 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
   1602    container_algorithm_internal::ContainerIter<Sequence>
   1603    c_max_element(Sequence& sequence, LessThan&& comp) {
   1604  return std::max_element(container_algorithm_internal::c_begin(sequence),
   1605                          container_algorithm_internal::c_end(sequence),
   1606                          std::forward<LessThan>(comp));
   1607 }
   1608 
   1609 // c_minmax_element()
   1610 //
   1611 // Container-based version of the <algorithm> `std::minmax_element()` function
   1612 // to return a pair of iterators pointing to the elements containing the
   1613 // smallest and largest values, respectively, using `operator<` to make the
   1614 // comparisons.
   1615 template <typename C>
   1616 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
   1617    container_algorithm_internal::ContainerIterPairType<C, C>
   1618    c_minmax_element(C& c) {
   1619  return std::minmax_element(container_algorithm_internal::c_begin(c),
   1620                             container_algorithm_internal::c_end(c));
   1621 }
   1622 
   1623 // Overload of c_minmax_element() for performing `comp` comparisons other than
   1624 // `operator<`.
   1625 template <typename C, typename LessThan>
   1626 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
   1627    container_algorithm_internal::ContainerIterPairType<C, C>
   1628    c_minmax_element(C& c, LessThan&& comp) {
   1629  return std::minmax_element(container_algorithm_internal::c_begin(c),
   1630                             container_algorithm_internal::c_end(c),
   1631                             std::forward<LessThan>(comp));
   1632 }
   1633 
   1634 //------------------------------------------------------------------------------
   1635 //  <algorithm> Lexicographical Comparisons
   1636 //------------------------------------------------------------------------------
   1637 
   1638 // c_lexicographical_compare()
   1639 //
   1640 // Container-based version of the <algorithm> `std::lexicographical_compare()`
   1641 // function to lexicographically compare (e.g. sort words alphabetically) two
   1642 // container sequences. The comparison is performed using `operator<`. Note
   1643 // that capital letters ("A-Z") have ASCII values less than lowercase letters
   1644 // ("a-z").
   1645 template <typename Sequence1, typename Sequence2>
   1646 bool c_lexicographical_compare(const Sequence1& sequence1,
   1647                               const Sequence2& sequence2) {
   1648  return std::lexicographical_compare(
   1649      container_algorithm_internal::c_begin(sequence1),
   1650      container_algorithm_internal::c_end(sequence1),
   1651      container_algorithm_internal::c_begin(sequence2),
   1652      container_algorithm_internal::c_end(sequence2));
   1653 }
   1654 
   1655 // Overload of c_lexicographical_compare() for performing a lexicographical
   1656 // comparison using a `comp` operator instead of `operator<`.
   1657 template <typename Sequence1, typename Sequence2, typename LessThan>
   1658 bool c_lexicographical_compare(const Sequence1& sequence1,
   1659                               const Sequence2& sequence2, LessThan&& comp) {
   1660  return std::lexicographical_compare(
   1661      container_algorithm_internal::c_begin(sequence1),
   1662      container_algorithm_internal::c_end(sequence1),
   1663      container_algorithm_internal::c_begin(sequence2),
   1664      container_algorithm_internal::c_end(sequence2),
   1665      std::forward<LessThan>(comp));
   1666 }
   1667 
   1668 // c_next_permutation()
   1669 //
   1670 // Container-based version of the <algorithm> `std::next_permutation()` function
   1671 // to rearrange a container's elements into the next lexicographically greater
   1672 // permutation.
   1673 template <typename C>
   1674 bool c_next_permutation(C& c) {
   1675  return std::next_permutation(container_algorithm_internal::c_begin(c),
   1676                               container_algorithm_internal::c_end(c));
   1677 }
   1678 
   1679 // Overload of c_next_permutation() for performing a lexicographical
   1680 // comparison using a `comp` operator instead of `operator<`.
   1681 template <typename C, typename LessThan>
   1682 bool c_next_permutation(C& c, LessThan&& comp) {
   1683  return std::next_permutation(container_algorithm_internal::c_begin(c),
   1684                               container_algorithm_internal::c_end(c),
   1685                               std::forward<LessThan>(comp));
   1686 }
   1687 
   1688 // c_prev_permutation()
   1689 //
   1690 // Container-based version of the <algorithm> `std::prev_permutation()` function
   1691 // to rearrange a container's elements into the next lexicographically lesser
   1692 // permutation.
   1693 template <typename C>
   1694 bool c_prev_permutation(C& c) {
   1695  return std::prev_permutation(container_algorithm_internal::c_begin(c),
   1696                               container_algorithm_internal::c_end(c));
   1697 }
   1698 
   1699 // Overload of c_prev_permutation() for performing a lexicographical
   1700 // comparison using a `comp` operator instead of `operator<`.
   1701 template <typename C, typename LessThan>
   1702 bool c_prev_permutation(C& c, LessThan&& comp) {
   1703  return std::prev_permutation(container_algorithm_internal::c_begin(c),
   1704                               container_algorithm_internal::c_end(c),
   1705                               std::forward<LessThan>(comp));
   1706 }
   1707 
   1708 //------------------------------------------------------------------------------
   1709 // <numeric> algorithms
   1710 //------------------------------------------------------------------------------
   1711 
   1712 // c_iota()
   1713 //
   1714 // Container-based version of the <numeric> `std::iota()` function
   1715 // to compute successive values of `value`, as if incremented with `++value`
   1716 // after each element is written, and write them to the container.
   1717 template <typename Sequence, typename T>
   1718 void c_iota(Sequence& sequence, const T& value) {
   1719  std::iota(container_algorithm_internal::c_begin(sequence),
   1720            container_algorithm_internal::c_end(sequence), value);
   1721 }
   1722 
   1723 // c_accumulate()
   1724 //
   1725 // Container-based version of the <numeric> `std::accumulate()` function
   1726 // to accumulate the element values of a container to `init` and return that
   1727 // accumulation by value.
   1728 //
   1729 // Note: Due to a language technicality this function has return type
   1730 // absl::decay_t<T>. As a user of this function you can casually read
   1731 // this as "returns T by value" and assume it does the right thing.
   1732 template <typename Sequence, typename T>
   1733 decay_t<T> c_accumulate(const Sequence& sequence, T&& init) {
   1734  return std::accumulate(container_algorithm_internal::c_begin(sequence),
   1735                         container_algorithm_internal::c_end(sequence),
   1736                         std::forward<T>(init));
   1737 }
   1738 
   1739 // Overload of c_accumulate() for using a binary operations other than
   1740 // addition for computing the accumulation.
   1741 template <typename Sequence, typename T, typename BinaryOp>
   1742 decay_t<T> c_accumulate(const Sequence& sequence, T&& init,
   1743                        BinaryOp&& binary_op) {
   1744  return std::accumulate(container_algorithm_internal::c_begin(sequence),
   1745                         container_algorithm_internal::c_end(sequence),
   1746                         std::forward<T>(init),
   1747                         std::forward<BinaryOp>(binary_op));
   1748 }
   1749 
   1750 // c_inner_product()
   1751 //
   1752 // Container-based version of the <numeric> `std::inner_product()` function
   1753 // to compute the cumulative inner product of container element pairs.
   1754 //
   1755 // Note: Due to a language technicality this function has return type
   1756 // absl::decay_t<T>. As a user of this function you can casually read
   1757 // this as "returns T by value" and assume it does the right thing.
   1758 template <typename Sequence1, typename Sequence2, typename T>
   1759 decay_t<T> c_inner_product(const Sequence1& factors1, const Sequence2& factors2,
   1760                           T&& sum) {
   1761  return std::inner_product(container_algorithm_internal::c_begin(factors1),
   1762                            container_algorithm_internal::c_end(factors1),
   1763                            container_algorithm_internal::c_begin(factors2),
   1764                            std::forward<T>(sum));
   1765 }
   1766 
   1767 // Overload of c_inner_product() for using binary operations other than
   1768 // `operator+` (for computing the accumulation) and `operator*` (for computing
   1769 // the product between the two container's element pair).
   1770 template <typename Sequence1, typename Sequence2, typename T,
   1771          typename BinaryOp1, typename BinaryOp2>
   1772 decay_t<T> c_inner_product(const Sequence1& factors1, const Sequence2& factors2,
   1773                           T&& sum, BinaryOp1&& op1, BinaryOp2&& op2) {
   1774  return std::inner_product(container_algorithm_internal::c_begin(factors1),
   1775                            container_algorithm_internal::c_end(factors1),
   1776                            container_algorithm_internal::c_begin(factors2),
   1777                            std::forward<T>(sum), std::forward<BinaryOp1>(op1),
   1778                            std::forward<BinaryOp2>(op2));
   1779 }
   1780 
   1781 // c_adjacent_difference()
   1782 //
   1783 // Container-based version of the <numeric> `std::adjacent_difference()`
   1784 // function to compute the difference between each element and the one preceding
   1785 // it and write it to an iterator.
   1786 template <typename InputSequence, typename OutputIt>
   1787 OutputIt c_adjacent_difference(const InputSequence& input,
   1788                               OutputIt output_first) {
   1789  return std::adjacent_difference(container_algorithm_internal::c_begin(input),
   1790                                  container_algorithm_internal::c_end(input),
   1791                                  output_first);
   1792 }
   1793 
   1794 // Overload of c_adjacent_difference() for using a binary operation other than
   1795 // subtraction to compute the adjacent difference.
   1796 template <typename InputSequence, typename OutputIt, typename BinaryOp>
   1797 OutputIt c_adjacent_difference(const InputSequence& input,
   1798                               OutputIt output_first, BinaryOp&& op) {
   1799  return std::adjacent_difference(container_algorithm_internal::c_begin(input),
   1800                                  container_algorithm_internal::c_end(input),
   1801                                  output_first, std::forward<BinaryOp>(op));
   1802 }
   1803 
   1804 // c_partial_sum()
   1805 //
   1806 // Container-based version of the <numeric> `std::partial_sum()` function
   1807 // to compute the partial sum of the elements in a sequence and write them
   1808 // to an iterator. The partial sum is the sum of all element values so far in
   1809 // the sequence.
   1810 template <typename InputSequence, typename OutputIt>
   1811 OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first) {
   1812  return std::partial_sum(container_algorithm_internal::c_begin(input),
   1813                          container_algorithm_internal::c_end(input),
   1814                          output_first);
   1815 }
   1816 
   1817 // Overload of c_partial_sum() for using a binary operation other than addition
   1818 // to compute the "partial sum".
   1819 template <typename InputSequence, typename OutputIt, typename BinaryOp>
   1820 OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first,
   1821                       BinaryOp&& op) {
   1822  return std::partial_sum(container_algorithm_internal::c_begin(input),
   1823                          container_algorithm_internal::c_end(input),
   1824                          output_first, std::forward<BinaryOp>(op));
   1825 }
   1826 
   1827 ABSL_NAMESPACE_END
   1828 }  // namespace absl
   1829 
   1830 #endif  // ABSL_ALGORITHM_CONTAINER_H_