Coverage Report

Created: 2026-10-28 06:49

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