Coverage Report

Created: 2026-09-14 06:45

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