blob: 679e02676c65b44ce0eb04ca1db82ba7d143011a [file] [log] [blame]
mistergc2e75482017-09-19 16:54:40 -04001// 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//
nik727338b70432019-03-08 10:27:53 -05007// https://www.apache.org/licenses/LICENSE-2.0
mistergc2e75482017-09-19 16:54:40 -04008//
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.
mistergc2e75482017-09-19 16:54:40 -040039
40#ifndef ABSL_ALGORITHM_CONTAINER_H_
41#define ABSL_ALGORITHM_CONTAINER_H_
42
43#include <algorithm>
44#include <cassert>
45#include <iterator>
46#include <numeric>
47#include <type_traits>
Abseil Team7b46e1d2018-11-13 13:22:00 -080048#include <unordered_map>
49#include <unordered_set>
mistergc2e75482017-09-19 16:54:40 -040050#include <utility>
51#include <vector>
52
53#include "absl/algorithm/algorithm.h"
54#include "absl/base/macros.h"
55#include "absl/meta/type_traits.h"
56
57namespace absl {
Abseil Team12bc53e2019-12-12 10:36:03 -080058ABSL_NAMESPACE_BEGIN
mistergc2e75482017-09-19 16:54:40 -040059namespace container_algorithm_internal {
60
61// NOTE: it is important to defer to ADL lookup for building with C++ modules,
62// especially for headers like <valarray> which are not visible from this file
63// but specialize std::begin and std::end.
64using std::begin;
65using std::end;
66
67// The type of the iterator given by begin(c) (possibly std::begin(c)).
68// ContainerIter<const vector<T>> gives vector<T>::const_iterator,
69// while ContainerIter<vector<T>> gives vector<T>::iterator.
70template <typename C>
71using ContainerIter = decltype(begin(std::declval<C&>()));
72
Abseil Team95ddf852017-11-13 10:04:29 -080073// An MSVC bug involving template parameter substitution requires us to use
74// decltype() here instead of just std::pair.
75template <typename C1, typename C2>
76using ContainerIterPairType =
77 decltype(std::make_pair(ContainerIter<C1>(), ContainerIter<C2>()));
78
mistergc2e75482017-09-19 16:54:40 -040079template <typename C>
Abseil Teamb8720b42023-01-23 11:51:06 -080080using ContainerDifferenceType = decltype(std::distance(
81 std::declval<ContainerIter<C>>(), std::declval<ContainerIter<C>>()));
mistergc2e75482017-09-19 16:54:40 -040082
83template <typename C>
84using ContainerPointerType =
85 typename std::iterator_traits<ContainerIter<C>>::pointer;
86
87// container_algorithm_internal::c_begin and
88// container_algorithm_internal::c_end are abbreviations for proper ADL
89// lookup of std::begin and std::end, i.e.
90// using std::begin;
91// using std::end;
Abseil Team4b4f9aa2020-10-05 08:30:57 -070092// std::foo(begin(c), end(c));
mistergc2e75482017-09-19 16:54:40 -040093// becomes
94// std::foo(container_algorithm_internal::begin(c),
Abseil Team4b2fbb42020-10-12 10:33:47 -070095// container_algorithm_internal::end(c));
mistergc2e75482017-09-19 16:54:40 -040096// These are meant for internal use only.
97
98template <typename C>
Abseil Teamb8720b42023-01-23 11:51:06 -080099ContainerIter<C> c_begin(C& c) {
100 return begin(c);
101}
mistergc2e75482017-09-19 16:54:40 -0400102
103template <typename C>
Abseil Teamb8720b42023-01-23 11:51:06 -0800104ContainerIter<C> c_end(C& c) {
105 return end(c);
106}
mistergc2e75482017-09-19 16:54:40 -0400107
Abseil Team7b46e1d2018-11-13 13:22:00 -0800108template <typename T>
109struct IsUnorderedContainer : std::false_type {};
110
111template <class Key, class T, class Hash, class KeyEqual, class Allocator>
112struct IsUnorderedContainer<
113 std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
114
115template <class Key, class Hash, class KeyEqual, class Allocator>
116struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
117 : std::true_type {};
118
Abseil Teamab3552a2019-10-15 18:18:40 -0700119// container_algorithm_internal::c_size. It is meant for internal use only.
120
121template <class C>
122auto c_size(C& c) -> decltype(c.size()) {
123 return c.size();
124}
125
126template <class T, std::size_t N>
127constexpr std::size_t c_size(T (&)[N]) {
128 return N;
129}
130
mistergc2e75482017-09-19 16:54:40 -0400131} // namespace container_algorithm_internal
132
133// PUBLIC API
134
135//------------------------------------------------------------------------------
136// Abseil algorithm.h functions
137//------------------------------------------------------------------------------
138
139// c_linear_search()
140//
141// Container-based version of absl::linear_search() for performing a linear
142// search within a container.
143template <typename C, typename EqualityComparable>
144bool c_linear_search(const C& c, EqualityComparable&& value) {
145 return linear_search(container_algorithm_internal::c_begin(c),
146 container_algorithm_internal::c_end(c),
147 std::forward<EqualityComparable>(value));
148}
149
150//------------------------------------------------------------------------------
151// <iterator> algorithms
152//------------------------------------------------------------------------------
153
154// c_distance()
155//
156// Container-based version of the <iterator> `std::distance()` function to
157// return the number of elements within a container.
158template <typename C>
159container_algorithm_internal::ContainerDifferenceType<const C> c_distance(
160 const C& c) {
161 return std::distance(container_algorithm_internal::c_begin(c),
162 container_algorithm_internal::c_end(c));
163}
164
165//------------------------------------------------------------------------------
166// <algorithm> Non-modifying sequence operations
167//------------------------------------------------------------------------------
168
169// c_all_of()
170//
171// Container-based version of the <algorithm> `std::all_of()` function to
Abseil Team299f59c2021-11-17 10:01:24 -0800172// test if all elements within a container satisfy a condition.
mistergc2e75482017-09-19 16:54:40 -0400173template <typename C, typename Pred>
174bool c_all_of(const C& c, Pred&& pred) {
175 return std::all_of(container_algorithm_internal::c_begin(c),
176 container_algorithm_internal::c_end(c),
177 std::forward<Pred>(pred));
178}
179
180// c_any_of()
181//
182// Container-based version of the <algorithm> `std::any_of()` function to
183// test if any element in a container fulfills a condition.
184template <typename C, typename Pred>
185bool c_any_of(const C& c, Pred&& pred) {
186 return std::any_of(container_algorithm_internal::c_begin(c),
187 container_algorithm_internal::c_end(c),
188 std::forward<Pred>(pred));
189}
190
191// c_none_of()
192//
193// Container-based version of the <algorithm> `std::none_of()` function to
Abseil Teamc9894d12020-10-30 10:38:44 -0700194// test if no elements in a container fulfill a condition.
mistergc2e75482017-09-19 16:54:40 -0400195template <typename C, typename Pred>
196bool c_none_of(const C& c, Pred&& pred) {
197 return std::none_of(container_algorithm_internal::c_begin(c),
198 container_algorithm_internal::c_end(c),
199 std::forward<Pred>(pred));
200}
201
202// c_for_each()
203//
204// Container-based version of the <algorithm> `std::for_each()` function to
205// apply a function to a container's elements.
206template <typename C, typename Function>
207decay_t<Function> c_for_each(C&& c, Function&& f) {
208 return std::for_each(container_algorithm_internal::c_begin(c),
209 container_algorithm_internal::c_end(c),
210 std::forward<Function>(f));
211}
212
213// c_find()
214//
215// Container-based version of the <algorithm> `std::find()` function to find
216// the first element containing the passed value within a container value.
217template <typename C, typename T>
218container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) {
219 return std::find(container_algorithm_internal::c_begin(c),
220 container_algorithm_internal::c_end(c),
221 std::forward<T>(value));
222}
223
224// c_find_if()
225//
226// Container-based version of the <algorithm> `std::find_if()` function to find
227// the first element in a container matching the given condition.
228template <typename C, typename Pred>
229container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) {
230 return std::find_if(container_algorithm_internal::c_begin(c),
231 container_algorithm_internal::c_end(c),
232 std::forward<Pred>(pred));
233}
234
235// c_find_if_not()
236//
237// Container-based version of the <algorithm> `std::find_if_not()` function to
238// find the first element in a container not matching the given condition.
239template <typename C, typename Pred>
240container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c,
241 Pred&& pred) {
242 return std::find_if_not(container_algorithm_internal::c_begin(c),
243 container_algorithm_internal::c_end(c),
244 std::forward<Pred>(pred));
245}
246
247// c_find_end()
248//
249// Container-based version of the <algorithm> `std::find_end()` function to
250// find the last subsequence within a container.
251template <typename Sequence1, typename Sequence2>
252container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
253 Sequence1& sequence, Sequence2& subsequence) {
254 return std::find_end(container_algorithm_internal::c_begin(sequence),
255 container_algorithm_internal::c_end(sequence),
256 container_algorithm_internal::c_begin(subsequence),
257 container_algorithm_internal::c_end(subsequence));
258}
259
260// Overload of c_find_end() for using a predicate evaluation other than `==` as
261// the function's test condition.
262template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
263container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
264 Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
265 return std::find_end(container_algorithm_internal::c_begin(sequence),
266 container_algorithm_internal::c_end(sequence),
267 container_algorithm_internal::c_begin(subsequence),
268 container_algorithm_internal::c_end(subsequence),
269 std::forward<BinaryPredicate>(pred));
270}
271
272// c_find_first_of()
273//
274// Container-based version of the <algorithm> `std::find_first_of()` function to
Abseil Teama4b757b2019-12-02 10:41:53 -0800275// find the first element within the container that is also within the options
276// container.
mistergc2e75482017-09-19 16:54:40 -0400277template <typename C1, typename C2>
278container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
279 C2& options) {
280 return std::find_first_of(container_algorithm_internal::c_begin(container),
281 container_algorithm_internal::c_end(container),
282 container_algorithm_internal::c_begin(options),
283 container_algorithm_internal::c_end(options));
284}
285
286// Overload of c_find_first_of() for using a predicate evaluation other than
287// `==` as the function's test condition.
288template <typename C1, typename C2, typename BinaryPredicate>
289container_algorithm_internal::ContainerIter<C1> c_find_first_of(
290 C1& container, C2& options, BinaryPredicate&& pred) {
291 return std::find_first_of(container_algorithm_internal::c_begin(container),
292 container_algorithm_internal::c_end(container),
293 container_algorithm_internal::c_begin(options),
294 container_algorithm_internal::c_end(options),
295 std::forward<BinaryPredicate>(pred));
296}
297
298// c_adjacent_find()
299//
300// Container-based version of the <algorithm> `std::adjacent_find()` function to
301// find equal adjacent elements within a container.
302template <typename Sequence>
303container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
304 Sequence& sequence) {
305 return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
306 container_algorithm_internal::c_end(sequence));
307}
308
309// Overload of c_adjacent_find() for using a predicate evaluation other than
310// `==` as the function's test condition.
311template <typename Sequence, typename BinaryPredicate>
312container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
313 Sequence& sequence, BinaryPredicate&& pred) {
314 return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
315 container_algorithm_internal::c_end(sequence),
316 std::forward<BinaryPredicate>(pred));
317}
318
319// c_count()
320//
321// Container-based version of the <algorithm> `std::count()` function to count
322// values that match within a container.
323template <typename C, typename T>
324container_algorithm_internal::ContainerDifferenceType<const C> c_count(
325 const C& c, T&& value) {
326 return std::count(container_algorithm_internal::c_begin(c),
327 container_algorithm_internal::c_end(c),
328 std::forward<T>(value));
329}
330
331// c_count_if()
332//
333// Container-based version of the <algorithm> `std::count_if()` function to
334// count values matching a condition within a container.
335template <typename C, typename Pred>
336container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
337 const C& c, Pred&& pred) {
338 return std::count_if(container_algorithm_internal::c_begin(c),
339 container_algorithm_internal::c_end(c),
340 std::forward<Pred>(pred));
341}
342
343// c_mismatch()
344//
Abseil Team42f22a22018-07-18 10:04:24 -0700345// Container-based version of the <algorithm> `std::mismatch()` function to
Abseil Team887d0ee2020-10-02 10:17:27 -0700346// return the first element where two ordered containers differ. Applies `==` to
347// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
mistergc2e75482017-09-19 16:54:40 -0400348template <typename C1, typename C2>
Abseil Teamb8720b42023-01-23 11:51:06 -0800349container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
350 C2& c2) {
Abseil Team887d0ee2020-10-02 10:17:27 -0700351 auto first1 = container_algorithm_internal::c_begin(c1);
352 auto last1 = container_algorithm_internal::c_end(c1);
353 auto first2 = container_algorithm_internal::c_begin(c2);
354 auto last2 = container_algorithm_internal::c_end(c2);
355
356 for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
Abseil Teame63a5a62020-10-08 08:27:41 -0700357 // Negates equality because Cpp17EqualityComparable doesn't require clients
358 // to overload both `operator==` and `operator!=`.
359 if (!(*first1 == *first2)) {
Abseil Team887d0ee2020-10-02 10:17:27 -0700360 break;
361 }
362 }
363
364 return std::make_pair(first1, first2);
mistergc2e75482017-09-19 16:54:40 -0400365}
366
367// Overload of c_mismatch() for using a predicate evaluation other than `==` as
Abseil Team887d0ee2020-10-02 10:17:27 -0700368// the function's test condition. Applies `pred`to the first N elements of `c1`
369// and `c2`, where N = min(size(c1), size(c2)).
mistergc2e75482017-09-19 16:54:40 -0400370template <typename C1, typename C2, typename BinaryPredicate>
Abseil Teamb8720b42023-01-23 11:51:06 -0800371container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(
372 C1& c1, C2& c2, BinaryPredicate pred) {
Abseil Team887d0ee2020-10-02 10:17:27 -0700373 auto first1 = container_algorithm_internal::c_begin(c1);
374 auto last1 = container_algorithm_internal::c_end(c1);
375 auto first2 = container_algorithm_internal::c_begin(c2);
376 auto last2 = container_algorithm_internal::c_end(c2);
377
378 for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
379 if (!pred(*first1, *first2)) {
380 break;
381 }
382 }
383
384 return std::make_pair(first1, first2);
mistergc2e75482017-09-19 16:54:40 -0400385}
386
387// c_equal()
388//
389// Container-based version of the <algorithm> `std::equal()` function to
390// test whether two containers are equal.
391//
392// NOTE: the semantics of c_equal() are slightly different than those of
393// equal(): while the latter iterates over the second container only up to the
394// size of the first container, c_equal() also checks whether the container
395// sizes are equal. This better matches expectations about c_equal() based on
396// its signature.
397//
398// Example:
399// vector v1 = <1, 2, 3>;
400// vector v2 = <1, 2, 3, 4>;
401// equal(std::begin(v1), std::end(v1), std::begin(v2)) returns true
402// c_equal(v1, v2) returns false
403
404template <typename C1, typename C2>
405bool c_equal(const C1& c1, const C2& c2) {
Abseil Teamab3552a2019-10-15 18:18:40 -0700406 return ((container_algorithm_internal::c_size(c1) ==
407 container_algorithm_internal::c_size(c2)) &&
mistergc2e75482017-09-19 16:54:40 -0400408 std::equal(container_algorithm_internal::c_begin(c1),
409 container_algorithm_internal::c_end(c1),
410 container_algorithm_internal::c_begin(c2)));
411}
412
413// Overload of c_equal() for using a predicate evaluation other than `==` as
414// the function's test condition.
415template <typename C1, typename C2, typename BinaryPredicate>
416bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
Abseil Teamab3552a2019-10-15 18:18:40 -0700417 return ((container_algorithm_internal::c_size(c1) ==
418 container_algorithm_internal::c_size(c2)) &&
mistergc2e75482017-09-19 16:54:40 -0400419 std::equal(container_algorithm_internal::c_begin(c1),
420 container_algorithm_internal::c_end(c1),
421 container_algorithm_internal::c_begin(c2),
422 std::forward<BinaryPredicate>(pred)));
423}
424
425// c_is_permutation()
426//
427// Container-based version of the <algorithm> `std::is_permutation()` function
428// to test whether a container is a permutation of another.
429template <typename C1, typename C2>
430bool c_is_permutation(const C1& c1, const C2& c2) {
431 using std::begin;
432 using std::end;
433 return c1.size() == c2.size() &&
434 std::is_permutation(begin(c1), end(c1), begin(c2));
435}
436
437// Overload of c_is_permutation() for using a predicate evaluation other than
438// `==` as the function's test condition.
439template <typename C1, typename C2, typename BinaryPredicate>
440bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
441 using std::begin;
442 using std::end;
443 return c1.size() == c2.size() &&
444 std::is_permutation(begin(c1), end(c1), begin(c2),
445 std::forward<BinaryPredicate>(pred));
446}
447
448// c_search()
449//
450// Container-based version of the <algorithm> `std::search()` function to search
451// a container for a subsequence.
452template <typename Sequence1, typename Sequence2>
453container_algorithm_internal::ContainerIter<Sequence1> c_search(
454 Sequence1& sequence, Sequence2& subsequence) {
455 return std::search(container_algorithm_internal::c_begin(sequence),
456 container_algorithm_internal::c_end(sequence),
457 container_algorithm_internal::c_begin(subsequence),
458 container_algorithm_internal::c_end(subsequence));
459}
460
461// Overload of c_search() for using a predicate evaluation other than
462// `==` as the function's test condition.
463template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
464container_algorithm_internal::ContainerIter<Sequence1> c_search(
465 Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
466 return std::search(container_algorithm_internal::c_begin(sequence),
467 container_algorithm_internal::c_end(sequence),
468 container_algorithm_internal::c_begin(subsequence),
469 container_algorithm_internal::c_end(subsequence),
470 std::forward<BinaryPredicate>(pred));
471}
472
473// c_search_n()
474//
475// Container-based version of the <algorithm> `std::search_n()` function to
476// search a container for the first sequence of N elements.
477template <typename Sequence, typename Size, typename T>
478container_algorithm_internal::ContainerIter<Sequence> c_search_n(
479 Sequence& sequence, Size count, T&& value) {
480 return std::search_n(container_algorithm_internal::c_begin(sequence),
481 container_algorithm_internal::c_end(sequence), count,
482 std::forward<T>(value));
483}
484
485// Overload of c_search_n() for using a predicate evaluation other than
486// `==` as the function's test condition.
487template <typename Sequence, typename Size, typename T,
488 typename BinaryPredicate>
489container_algorithm_internal::ContainerIter<Sequence> c_search_n(
490 Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) {
491 return std::search_n(container_algorithm_internal::c_begin(sequence),
492 container_algorithm_internal::c_end(sequence), count,
493 std::forward<T>(value),
494 std::forward<BinaryPredicate>(pred));
495}
496
497//------------------------------------------------------------------------------
498// <algorithm> Modifying sequence operations
499//------------------------------------------------------------------------------
500
501// c_copy()
502//
503// Container-based version of the <algorithm> `std::copy()` function to copy a
504// container's elements into an iterator.
505template <typename InputSequence, typename OutputIterator>
506OutputIterator c_copy(const InputSequence& input, OutputIterator output) {
507 return std::copy(container_algorithm_internal::c_begin(input),
508 container_algorithm_internal::c_end(input), output);
509}
510
511// c_copy_n()
512//
513// Container-based version of the <algorithm> `std::copy_n()` function to copy a
514// container's first N elements into an iterator.
515template <typename C, typename Size, typename OutputIterator>
516OutputIterator c_copy_n(const C& input, Size n, OutputIterator output) {
517 return std::copy_n(container_algorithm_internal::c_begin(input), n, output);
518}
519
520// c_copy_if()
521//
522// Container-based version of the <algorithm> `std::copy_if()` function to copy
523// a container's elements satisfying some condition into an iterator.
524template <typename InputSequence, typename OutputIterator, typename Pred>
525OutputIterator c_copy_if(const InputSequence& input, OutputIterator output,
526 Pred&& pred) {
527 return std::copy_if(container_algorithm_internal::c_begin(input),
528 container_algorithm_internal::c_end(input), output,
529 std::forward<Pred>(pred));
530}
531
532// c_copy_backward()
533//
534// Container-based version of the <algorithm> `std::copy_backward()` function to
535// copy a container's elements in reverse order into an iterator.
536template <typename C, typename BidirectionalIterator>
537BidirectionalIterator c_copy_backward(const C& src,
538 BidirectionalIterator dest) {
539 return std::copy_backward(container_algorithm_internal::c_begin(src),
540 container_algorithm_internal::c_end(src), dest);
541}
542
543// c_move()
544//
545// Container-based version of the <algorithm> `std::move()` function to move
546// a container's elements into an iterator.
547template <typename C, typename OutputIterator>
Abseil Team02451912018-09-11 11:22:56 -0700548OutputIterator c_move(C&& src, OutputIterator dest) {
mistergc2e75482017-09-19 16:54:40 -0400549 return std::move(container_algorithm_internal::c_begin(src),
550 container_algorithm_internal::c_end(src), dest);
551}
552
Abseil Team72e09a52019-06-25 12:32:44 -0700553// c_move_backward()
554//
555// Container-based version of the <algorithm> `std::move_backward()` function to
556// move a container's elements into an iterator in reverse order.
557template <typename C, typename BidirectionalIterator>
558BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator dest) {
559 return std::move_backward(container_algorithm_internal::c_begin(src),
560 container_algorithm_internal::c_end(src), dest);
561}
562
mistergc2e75482017-09-19 16:54:40 -0400563// c_swap_ranges()
564//
565// Container-based version of the <algorithm> `std::swap_ranges()` function to
Abseil Team093cc272020-09-30 13:36:40 -0700566// swap a container's elements with another container's elements. Swaps the
567// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
mistergc2e75482017-09-19 16:54:40 -0400568template <typename C1, typename C2>
569container_algorithm_internal::ContainerIter<C2> c_swap_ranges(C1& c1, C2& c2) {
Abseil Team093cc272020-09-30 13:36:40 -0700570 auto first1 = container_algorithm_internal::c_begin(c1);
571 auto last1 = container_algorithm_internal::c_end(c1);
572 auto first2 = container_algorithm_internal::c_begin(c2);
573 auto last2 = container_algorithm_internal::c_end(c2);
574
575 using std::swap;
576 for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
577 swap(*first1, *first2);
578 }
579 return first2;
mistergc2e75482017-09-19 16:54:40 -0400580}
581
582// c_transform()
583//
584// Container-based version of the <algorithm> `std::transform()` function to
585// transform a container's elements using the unary operation, storing the
586// result in an iterator pointing to the last transformed element in the output
587// range.
588template <typename InputSequence, typename OutputIterator, typename UnaryOp>
589OutputIterator c_transform(const InputSequence& input, OutputIterator output,
590 UnaryOp&& unary_op) {
591 return std::transform(container_algorithm_internal::c_begin(input),
592 container_algorithm_internal::c_end(input), output,
593 std::forward<UnaryOp>(unary_op));
594}
595
596// Overload of c_transform() for performing a transformation using a binary
Abseil Team093cc272020-09-30 13:36:40 -0700597// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,
598// where N = min(size(c1), size(c2)).
mistergc2e75482017-09-19 16:54:40 -0400599template <typename InputSequence1, typename InputSequence2,
600 typename OutputIterator, typename BinaryOp>
601OutputIterator c_transform(const InputSequence1& input1,
602 const InputSequence2& input2, OutputIterator output,
603 BinaryOp&& binary_op) {
Abseil Team093cc272020-09-30 13:36:40 -0700604 auto first1 = container_algorithm_internal::c_begin(input1);
605 auto last1 = container_algorithm_internal::c_end(input1);
606 auto first2 = container_algorithm_internal::c_begin(input2);
607 auto last2 = container_algorithm_internal::c_end(input2);
608 for (; first1 != last1 && first2 != last2;
609 ++first1, (void)++first2, ++output) {
610 *output = binary_op(*first1, *first2);
611 }
612
613 return output;
mistergc2e75482017-09-19 16:54:40 -0400614}
615
616// c_replace()
617//
618// Container-based version of the <algorithm> `std::replace()` function to
619// replace a container's elements of some value with a new value. The container
620// is modified in place.
621template <typename Sequence, typename T>
622void c_replace(Sequence& sequence, const T& old_value, const T& new_value) {
623 std::replace(container_algorithm_internal::c_begin(sequence),
624 container_algorithm_internal::c_end(sequence), old_value,
625 new_value);
626}
627
628// c_replace_if()
629//
630// Container-based version of the <algorithm> `std::replace_if()` function to
631// replace a container's elements of some value with a new value based on some
632// condition. The container is modified in place.
633template <typename C, typename Pred, typename T>
634void c_replace_if(C& c, Pred&& pred, T&& new_value) {
635 std::replace_if(container_algorithm_internal::c_begin(c),
636 container_algorithm_internal::c_end(c),
637 std::forward<Pred>(pred), std::forward<T>(new_value));
638}
639
640// c_replace_copy()
641//
642// Container-based version of the <algorithm> `std::replace_copy()` function to
643// replace a container's elements of some value with a new value and return the
644// results within an iterator.
645template <typename C, typename OutputIterator, typename T>
646OutputIterator c_replace_copy(const C& c, OutputIterator result, T&& old_value,
647 T&& new_value) {
648 return std::replace_copy(container_algorithm_internal::c_begin(c),
649 container_algorithm_internal::c_end(c), result,
650 std::forward<T>(old_value),
651 std::forward<T>(new_value));
652}
653
654// c_replace_copy_if()
655//
656// Container-based version of the <algorithm> `std::replace_copy_if()` function
657// to replace a container's elements of some value with a new value based on
658// some condition, and return the results within an iterator.
659template <typename C, typename OutputIterator, typename Pred, typename T>
660OutputIterator c_replace_copy_if(const C& c, OutputIterator result, Pred&& pred,
Abseil Teamb8720b42023-01-23 11:51:06 -0800661 const T& new_value) {
mistergc2e75482017-09-19 16:54:40 -0400662 return std::replace_copy_if(container_algorithm_internal::c_begin(c),
663 container_algorithm_internal::c_end(c), result,
Abseil Teamb8720b42023-01-23 11:51:06 -0800664 std::forward<Pred>(pred), new_value);
mistergc2e75482017-09-19 16:54:40 -0400665}
666
667// c_fill()
668//
669// Container-based version of the <algorithm> `std::fill()` function to fill a
670// container with some value.
671template <typename C, typename T>
Abseil Teamb8720b42023-01-23 11:51:06 -0800672void c_fill(C& c, const T& value) {
mistergc2e75482017-09-19 16:54:40 -0400673 std::fill(container_algorithm_internal::c_begin(c),
Abseil Teamb8720b42023-01-23 11:51:06 -0800674 container_algorithm_internal::c_end(c), value);
mistergc2e75482017-09-19 16:54:40 -0400675}
676
677// c_fill_n()
678//
679// Container-based version of the <algorithm> `std::fill_n()` function to fill
680// the first N elements in a container with some value.
681template <typename C, typename Size, typename T>
Abseil Teamb8720b42023-01-23 11:51:06 -0800682void c_fill_n(C& c, Size n, const T& value) {
683 std::fill_n(container_algorithm_internal::c_begin(c), n, value);
mistergc2e75482017-09-19 16:54:40 -0400684}
685
686// c_generate()
687//
688// Container-based version of the <algorithm> `std::generate()` function to
689// assign a container's elements to the values provided by the given generator.
690template <typename C, typename Generator>
691void c_generate(C& c, Generator&& gen) {
692 std::generate(container_algorithm_internal::c_begin(c),
693 container_algorithm_internal::c_end(c),
694 std::forward<Generator>(gen));
695}
696
697// c_generate_n()
698//
699// Container-based version of the <algorithm> `std::generate_n()` function to
700// assign a container's first N elements to the values provided by the given
701// generator.
702template <typename C, typename Size, typename Generator>
703container_algorithm_internal::ContainerIter<C> c_generate_n(C& c, Size n,
704 Generator&& gen) {
705 return std::generate_n(container_algorithm_internal::c_begin(c), n,
706 std::forward<Generator>(gen));
707}
708
709// Note: `c_xx()` <algorithm> container versions for `remove()`, `remove_if()`,
710// and `unique()` are omitted, because it's not clear whether or not such
Abseil Team87a4c072018-06-25 09:18:19 -0700711// functions should call erase on their supplied sequences afterwards. Either
mistergc2e75482017-09-19 16:54:40 -0400712// behavior would be surprising for a different set of users.
mistergc2e75482017-09-19 16:54:40 -0400713
714// c_remove_copy()
715//
716// Container-based version of the <algorithm> `std::remove_copy()` function to
717// copy a container's elements while removing any elements matching the given
718// `value`.
719template <typename C, typename OutputIterator, typename T>
Abseil Teamb8720b42023-01-23 11:51:06 -0800720OutputIterator c_remove_copy(const C& c, OutputIterator result,
721 const T& value) {
mistergc2e75482017-09-19 16:54:40 -0400722 return std::remove_copy(container_algorithm_internal::c_begin(c),
723 container_algorithm_internal::c_end(c), result,
Abseil Teamb8720b42023-01-23 11:51:06 -0800724 value);
mistergc2e75482017-09-19 16:54:40 -0400725}
726
727// c_remove_copy_if()
728//
729// Container-based version of the <algorithm> `std::remove_copy_if()` function
730// to copy a container's elements while removing any elements matching the given
731// condition.
732template <typename C, typename OutputIterator, typename Pred>
733OutputIterator c_remove_copy_if(const C& c, OutputIterator result,
734 Pred&& pred) {
735 return std::remove_copy_if(container_algorithm_internal::c_begin(c),
736 container_algorithm_internal::c_end(c), result,
737 std::forward<Pred>(pred));
738}
739
740// c_unique_copy()
741//
742// Container-based version of the <algorithm> `std::unique_copy()` function to
743// copy a container's elements while removing any elements containing duplicate
744// values.
745template <typename C, typename OutputIterator>
746OutputIterator c_unique_copy(const C& c, OutputIterator result) {
747 return std::unique_copy(container_algorithm_internal::c_begin(c),
748 container_algorithm_internal::c_end(c), result);
749}
750
751// Overload of c_unique_copy() for using a predicate evaluation other than
752// `==` for comparing uniqueness of the element values.
753template <typename C, typename OutputIterator, typename BinaryPredicate>
754OutputIterator c_unique_copy(const C& c, OutputIterator result,
755 BinaryPredicate&& pred) {
756 return std::unique_copy(container_algorithm_internal::c_begin(c),
757 container_algorithm_internal::c_end(c), result,
758 std::forward<BinaryPredicate>(pred));
759}
760
761// c_reverse()
762//
763// Container-based version of the <algorithm> `std::reverse()` function to
764// reverse a container's elements.
765template <typename Sequence>
766void c_reverse(Sequence& sequence) {
767 std::reverse(container_algorithm_internal::c_begin(sequence),
768 container_algorithm_internal::c_end(sequence));
769}
770
771// c_reverse_copy()
772//
773// Container-based version of the <algorithm> `std::reverse()` function to
774// reverse a container's elements and write them to an iterator range.
775template <typename C, typename OutputIterator>
776OutputIterator c_reverse_copy(const C& sequence, OutputIterator result) {
777 return std::reverse_copy(container_algorithm_internal::c_begin(sequence),
778 container_algorithm_internal::c_end(sequence),
779 result);
780}
781
782// c_rotate()
783//
784// Container-based version of the <algorithm> `std::rotate()` function to
785// shift a container's elements leftward such that the `middle` element becomes
786// the first element in the container.
787template <typename C,
788 typename Iterator = container_algorithm_internal::ContainerIter<C>>
789Iterator c_rotate(C& sequence, Iterator middle) {
790 return absl::rotate(container_algorithm_internal::c_begin(sequence), middle,
791 container_algorithm_internal::c_end(sequence));
792}
793
794// c_rotate_copy()
795//
796// Container-based version of the <algorithm> `std::rotate_copy()` function to
797// shift a container's elements leftward such that the `middle` element becomes
798// the first element in a new iterator range.
799template <typename C, typename OutputIterator>
800OutputIterator c_rotate_copy(
801 const C& sequence,
802 container_algorithm_internal::ContainerIter<const C> middle,
803 OutputIterator result) {
804 return std::rotate_copy(container_algorithm_internal::c_begin(sequence),
805 middle, container_algorithm_internal::c_end(sequence),
806 result);
807}
808
809// c_shuffle()
810//
811// Container-based version of the <algorithm> `std::shuffle()` function to
812// randomly shuffle elements within the container using a `gen()` uniform random
813// number generator.
814template <typename RandomAccessContainer, typename UniformRandomBitGenerator>
815void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) {
816 std::shuffle(container_algorithm_internal::c_begin(c),
817 container_algorithm_internal::c_end(c),
818 std::forward<UniformRandomBitGenerator>(gen));
819}
820
821//------------------------------------------------------------------------------
822// <algorithm> Partition functions
823//------------------------------------------------------------------------------
824
825// c_is_partitioned()
826//
827// Container-based version of the <algorithm> `std::is_partitioned()` function
828// to test whether all elements in the container for which `pred` returns `true`
829// precede those for which `pred` is `false`.
830template <typename C, typename Pred>
831bool c_is_partitioned(const C& c, Pred&& pred) {
832 return std::is_partitioned(container_algorithm_internal::c_begin(c),
833 container_algorithm_internal::c_end(c),
834 std::forward<Pred>(pred));
835}
836
837// c_partition()
838//
839// Container-based version of the <algorithm> `std::partition()` function
840// to rearrange all elements in a container in such a way that all elements for
841// which `pred` returns `true` precede all those for which it returns `false`,
842// returning an iterator to the first element of the second group.
843template <typename C, typename Pred>
844container_algorithm_internal::ContainerIter<C> c_partition(C& c, Pred&& pred) {
845 return std::partition(container_algorithm_internal::c_begin(c),
846 container_algorithm_internal::c_end(c),
847 std::forward<Pred>(pred));
848}
849
850// c_stable_partition()
851//
852// Container-based version of the <algorithm> `std::stable_partition()` function
853// to rearrange all elements in a container in such a way that all elements for
854// which `pred` returns `true` precede all those for which it returns `false`,
855// preserving the relative ordering between the two groups. The function returns
856// an iterator to the first element of the second group.
857template <typename C, typename Pred>
858container_algorithm_internal::ContainerIter<C> c_stable_partition(C& c,
859 Pred&& pred) {
860 return std::stable_partition(container_algorithm_internal::c_begin(c),
861 container_algorithm_internal::c_end(c),
862 std::forward<Pred>(pred));
863}
864
865// c_partition_copy()
866//
867// Container-based version of the <algorithm> `std::partition_copy()` function
868// to partition a container's elements and return them into two iterators: one
869// for which `pred` returns `true`, and one for which `pred` returns `false.`
870
871template <typename C, typename OutputIterator1, typename OutputIterator2,
872 typename Pred>
873std::pair<OutputIterator1, OutputIterator2> c_partition_copy(
874 const C& c, OutputIterator1 out_true, OutputIterator2 out_false,
875 Pred&& pred) {
876 return std::partition_copy(container_algorithm_internal::c_begin(c),
877 container_algorithm_internal::c_end(c), out_true,
878 out_false, std::forward<Pred>(pred));
879}
880
881// c_partition_point()
882//
883// Container-based version of the <algorithm> `std::partition_point()` function
884// to return the first element of an already partitioned container for which
885// the given `pred` is not `true`.
886template <typename C, typename Pred>
887container_algorithm_internal::ContainerIter<C> c_partition_point(C& c,
888 Pred&& pred) {
889 return std::partition_point(container_algorithm_internal::c_begin(c),
890 container_algorithm_internal::c_end(c),
891 std::forward<Pred>(pred));
892}
893
894//------------------------------------------------------------------------------
895// <algorithm> Sorting functions
896//------------------------------------------------------------------------------
897
898// c_sort()
899//
900// Container-based version of the <algorithm> `std::sort()` function
901// to sort elements in ascending order of their values.
902template <typename C>
903void c_sort(C& c) {
904 std::sort(container_algorithm_internal::c_begin(c),
905 container_algorithm_internal::c_end(c));
906}
907
908// Overload of c_sort() for performing a `comp` comparison other than the
909// default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -0700910template <typename C, typename LessThan>
911void c_sort(C& c, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -0400912 std::sort(container_algorithm_internal::c_begin(c),
913 container_algorithm_internal::c_end(c),
Abseil Team1ae9b712021-04-20 07:17:48 -0700914 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -0400915}
916
917// c_stable_sort()
918//
919// Container-based version of the <algorithm> `std::stable_sort()` function
920// to sort elements in ascending order of their values, preserving the order
921// of equivalents.
922template <typename C>
923void c_stable_sort(C& c) {
924 std::stable_sort(container_algorithm_internal::c_begin(c),
925 container_algorithm_internal::c_end(c));
926}
927
928// Overload of c_stable_sort() for performing a `comp` comparison other than the
929// default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -0700930template <typename C, typename LessThan>
931void c_stable_sort(C& c, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -0400932 std::stable_sort(container_algorithm_internal::c_begin(c),
933 container_algorithm_internal::c_end(c),
Abseil Team1ae9b712021-04-20 07:17:48 -0700934 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -0400935}
936
937// c_is_sorted()
938//
939// Container-based version of the <algorithm> `std::is_sorted()` function
Abseil Team95ddf852017-11-13 10:04:29 -0800940// to evaluate whether the given container is sorted in ascending order.
mistergc2e75482017-09-19 16:54:40 -0400941template <typename C>
942bool c_is_sorted(const C& c) {
943 return std::is_sorted(container_algorithm_internal::c_begin(c),
944 container_algorithm_internal::c_end(c));
945}
946
947// c_is_sorted() overload for performing a `comp` comparison other than the
948// default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -0700949template <typename C, typename LessThan>
950bool c_is_sorted(const C& c, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -0400951 return std::is_sorted(container_algorithm_internal::c_begin(c),
952 container_algorithm_internal::c_end(c),
Abseil Team1ae9b712021-04-20 07:17:48 -0700953 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -0400954}
955
956// c_partial_sort()
957//
958// Container-based version of the <algorithm> `std::partial_sort()` function
959// to rearrange elements within a container such that elements before `middle`
960// are sorted in ascending order.
961template <typename RandomAccessContainer>
962void c_partial_sort(
963 RandomAccessContainer& sequence,
964 container_algorithm_internal::ContainerIter<RandomAccessContainer> middle) {
965 std::partial_sort(container_algorithm_internal::c_begin(sequence), middle,
966 container_algorithm_internal::c_end(sequence));
967}
968
969// Overload of c_partial_sort() for performing a `comp` comparison other than
970// the default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -0700971template <typename RandomAccessContainer, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -0400972void c_partial_sort(
973 RandomAccessContainer& sequence,
974 container_algorithm_internal::ContainerIter<RandomAccessContainer> middle,
Abseil Team1ae9b712021-04-20 07:17:48 -0700975 LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -0400976 std::partial_sort(container_algorithm_internal::c_begin(sequence), middle,
977 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -0700978 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -0400979}
980
981// c_partial_sort_copy()
982//
983// Container-based version of the <algorithm> `std::partial_sort_copy()`
Abseil Teamda3a8762020-06-02 11:09:12 -0700984// function to sort the elements in the given range `result` within the larger
985// `sequence` in ascending order (and using `result` as the output parameter).
986// At most min(result.last - result.first, sequence.last - sequence.first)
987// elements from the sequence will be stored in the result.
mistergc2e75482017-09-19 16:54:40 -0400988template <typename C, typename RandomAccessContainer>
989container_algorithm_internal::ContainerIter<RandomAccessContainer>
990c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {
991 return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence),
992 container_algorithm_internal::c_end(sequence),
993 container_algorithm_internal::c_begin(result),
994 container_algorithm_internal::c_end(result));
995}
996
997// Overload of c_partial_sort_copy() for performing a `comp` comparison other
998// than the default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -0700999template <typename C, typename RandomAccessContainer, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001000container_algorithm_internal::ContainerIter<RandomAccessContainer>
1001c_partial_sort_copy(const C& sequence, RandomAccessContainer& result,
Abseil Team1ae9b712021-04-20 07:17:48 -07001002 LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001003 return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence),
1004 container_algorithm_internal::c_end(sequence),
1005 container_algorithm_internal::c_begin(result),
1006 container_algorithm_internal::c_end(result),
Abseil Team1ae9b712021-04-20 07:17:48 -07001007 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001008}
1009
1010// c_is_sorted_until()
1011//
1012// Container-based version of the <algorithm> `std::is_sorted_until()` function
1013// to return the first element within a container that is not sorted in
1014// ascending order as an iterator.
1015template <typename C>
1016container_algorithm_internal::ContainerIter<C> c_is_sorted_until(C& c) {
1017 return std::is_sorted_until(container_algorithm_internal::c_begin(c),
1018 container_algorithm_internal::c_end(c));
1019}
1020
1021// Overload of c_is_sorted_until() for performing a `comp` comparison other than
1022// the default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001023template <typename C, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001024container_algorithm_internal::ContainerIter<C> c_is_sorted_until(
Abseil Team1ae9b712021-04-20 07:17:48 -07001025 C& c, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001026 return std::is_sorted_until(container_algorithm_internal::c_begin(c),
1027 container_algorithm_internal::c_end(c),
Abseil Team1ae9b712021-04-20 07:17:48 -07001028 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001029}
1030
1031// c_nth_element()
1032//
1033// Container-based version of the <algorithm> `std::nth_element()` function
1034// to rearrange the elements within a container such that the `nth` element
1035// would be in that position in an ordered sequence; other elements may be in
1036// any order, except that all preceding `nth` will be less than that element,
1037// and all following `nth` will be greater than that element.
1038template <typename RandomAccessContainer>
1039void c_nth_element(
1040 RandomAccessContainer& sequence,
1041 container_algorithm_internal::ContainerIter<RandomAccessContainer> nth) {
1042 std::nth_element(container_algorithm_internal::c_begin(sequence), nth,
1043 container_algorithm_internal::c_end(sequence));
1044}
1045
1046// Overload of c_nth_element() for performing a `comp` comparison other than
1047// the default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001048template <typename RandomAccessContainer, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001049void c_nth_element(
1050 RandomAccessContainer& sequence,
1051 container_algorithm_internal::ContainerIter<RandomAccessContainer> nth,
Abseil Team1ae9b712021-04-20 07:17:48 -07001052 LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001053 std::nth_element(container_algorithm_internal::c_begin(sequence), nth,
1054 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -07001055 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001056}
1057
1058//------------------------------------------------------------------------------
1059// <algorithm> Binary Search
1060//------------------------------------------------------------------------------
1061
1062// c_lower_bound()
1063//
1064// Container-based version of the <algorithm> `std::lower_bound()` function
1065// to return an iterator pointing to the first element in a sorted container
1066// which does not compare less than `value`.
1067template <typename Sequence, typename T>
1068container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
Abseil Teamb8720b42023-01-23 11:51:06 -08001069 Sequence& sequence, const T& value) {
mistergc2e75482017-09-19 16:54:40 -04001070 return std::lower_bound(container_algorithm_internal::c_begin(sequence),
Abseil Teamb8720b42023-01-23 11:51:06 -08001071 container_algorithm_internal::c_end(sequence), value);
mistergc2e75482017-09-19 16:54:40 -04001072}
1073
1074// Overload of c_lower_bound() for performing a `comp` comparison other than
1075// the default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001076template <typename Sequence, typename T, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001077container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
Abseil Teamb8720b42023-01-23 11:51:06 -08001078 Sequence& sequence, const T& value, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001079 return std::lower_bound(container_algorithm_internal::c_begin(sequence),
Abseil Teamb8720b42023-01-23 11:51:06 -08001080 container_algorithm_internal::c_end(sequence), value,
1081 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001082}
1083
1084// c_upper_bound()
1085//
1086// Container-based version of the <algorithm> `std::upper_bound()` function
1087// to return an iterator pointing to the first element in a sorted container
1088// which is greater than `value`.
1089template <typename Sequence, typename T>
1090container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
Abseil Teamb8720b42023-01-23 11:51:06 -08001091 Sequence& sequence, const T& value) {
mistergc2e75482017-09-19 16:54:40 -04001092 return std::upper_bound(container_algorithm_internal::c_begin(sequence),
Abseil Teamb8720b42023-01-23 11:51:06 -08001093 container_algorithm_internal::c_end(sequence), value);
mistergc2e75482017-09-19 16:54:40 -04001094}
1095
1096// Overload of c_upper_bound() for performing a `comp` comparison other than
1097// the default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001098template <typename Sequence, typename T, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001099container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
Abseil Teamb8720b42023-01-23 11:51:06 -08001100 Sequence& sequence, const T& value, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001101 return std::upper_bound(container_algorithm_internal::c_begin(sequence),
Abseil Teamb8720b42023-01-23 11:51:06 -08001102 container_algorithm_internal::c_end(sequence), value,
1103 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001104}
1105
1106// c_equal_range()
1107//
1108// Container-based version of the <algorithm> `std::equal_range()` function
1109// to return an iterator pair pointing to the first and last elements in a
1110// sorted container which compare equal to `value`.
1111template <typename Sequence, typename T>
Abseil Team95ddf852017-11-13 10:04:29 -08001112container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
Abseil Teamb8720b42023-01-23 11:51:06 -08001113c_equal_range(Sequence& sequence, const T& value) {
mistergc2e75482017-09-19 16:54:40 -04001114 return std::equal_range(container_algorithm_internal::c_begin(sequence),
Abseil Teamb8720b42023-01-23 11:51:06 -08001115 container_algorithm_internal::c_end(sequence), value);
mistergc2e75482017-09-19 16:54:40 -04001116}
1117
1118// Overload of c_equal_range() for performing a `comp` comparison other than
1119// the default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001120template <typename Sequence, typename T, typename LessThan>
Abseil Team95ddf852017-11-13 10:04:29 -08001121container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
Abseil Teamb8720b42023-01-23 11:51:06 -08001122c_equal_range(Sequence& sequence, const T& value, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001123 return std::equal_range(container_algorithm_internal::c_begin(sequence),
Abseil Teamb8720b42023-01-23 11:51:06 -08001124 container_algorithm_internal::c_end(sequence), value,
1125 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001126}
1127
1128// c_binary_search()
1129//
1130// Container-based version of the <algorithm> `std::binary_search()` function
1131// to test if any element in the sorted container contains a value equivalent to
1132// 'value'.
1133template <typename Sequence, typename T>
Abseil Team1a38bea2023-01-31 16:37:12 -08001134bool c_binary_search(const Sequence& sequence, const T& value) {
mistergc2e75482017-09-19 16:54:40 -04001135 return std::binary_search(container_algorithm_internal::c_begin(sequence),
1136 container_algorithm_internal::c_end(sequence),
Abseil Teamb8720b42023-01-23 11:51:06 -08001137 value);
mistergc2e75482017-09-19 16:54:40 -04001138}
1139
1140// Overload of c_binary_search() for performing a `comp` comparison other than
1141// the default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001142template <typename Sequence, typename T, typename LessThan>
Abseil Team1a38bea2023-01-31 16:37:12 -08001143bool c_binary_search(const Sequence& sequence, const T& value,
1144 LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001145 return std::binary_search(container_algorithm_internal::c_begin(sequence),
1146 container_algorithm_internal::c_end(sequence),
Abseil Teamb8720b42023-01-23 11:51:06 -08001147 value, std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001148}
1149
1150//------------------------------------------------------------------------------
1151// <algorithm> Merge functions
1152//------------------------------------------------------------------------------
1153
1154// c_merge()
1155//
1156// Container-based version of the <algorithm> `std::merge()` function
1157// to merge two sorted containers into a single sorted iterator.
1158template <typename C1, typename C2, typename OutputIterator>
1159OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result) {
1160 return std::merge(container_algorithm_internal::c_begin(c1),
1161 container_algorithm_internal::c_end(c1),
1162 container_algorithm_internal::c_begin(c2),
1163 container_algorithm_internal::c_end(c2), result);
1164}
1165
1166// Overload of c_merge() for performing a `comp` comparison other than
1167// the default `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001168template <typename C1, typename C2, typename OutputIterator, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001169OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result,
Abseil Team1ae9b712021-04-20 07:17:48 -07001170 LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001171 return std::merge(container_algorithm_internal::c_begin(c1),
1172 container_algorithm_internal::c_end(c1),
1173 container_algorithm_internal::c_begin(c2),
1174 container_algorithm_internal::c_end(c2), result,
Abseil Team1ae9b712021-04-20 07:17:48 -07001175 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001176}
1177
1178// c_inplace_merge()
1179//
1180// Container-based version of the <algorithm> `std::inplace_merge()` function
1181// to merge a supplied iterator `middle` into a container.
1182template <typename C>
1183void c_inplace_merge(C& c,
1184 container_algorithm_internal::ContainerIter<C> middle) {
1185 std::inplace_merge(container_algorithm_internal::c_begin(c), middle,
1186 container_algorithm_internal::c_end(c));
1187}
1188
1189// Overload of c_inplace_merge() for performing a merge using a `comp` other
1190// than `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001191template <typename C, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001192void c_inplace_merge(C& c,
1193 container_algorithm_internal::ContainerIter<C> middle,
Abseil Team1ae9b712021-04-20 07:17:48 -07001194 LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001195 std::inplace_merge(container_algorithm_internal::c_begin(c), middle,
1196 container_algorithm_internal::c_end(c),
Abseil Team1ae9b712021-04-20 07:17:48 -07001197 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001198}
1199
1200// c_includes()
1201//
1202// Container-based version of the <algorithm> `std::includes()` function
1203// to test whether a sorted container `c1` entirely contains another sorted
1204// container `c2`.
1205template <typename C1, typename C2>
1206bool c_includes(const C1& c1, const C2& c2) {
1207 return std::includes(container_algorithm_internal::c_begin(c1),
1208 container_algorithm_internal::c_end(c1),
1209 container_algorithm_internal::c_begin(c2),
1210 container_algorithm_internal::c_end(c2));
1211}
1212
1213// Overload of c_includes() for performing a merge using a `comp` other than
1214// `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001215template <typename C1, typename C2, typename LessThan>
1216bool c_includes(const C1& c1, const C2& c2, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001217 return std::includes(container_algorithm_internal::c_begin(c1),
1218 container_algorithm_internal::c_end(c1),
1219 container_algorithm_internal::c_begin(c2),
1220 container_algorithm_internal::c_end(c2),
Abseil Team1ae9b712021-04-20 07:17:48 -07001221 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001222}
1223
1224// c_set_union()
1225//
1226// Container-based version of the <algorithm> `std::set_union()` function
1227// to return an iterator containing the union of two containers; duplicate
1228// values are not copied into the output.
Abseil Team7b46e1d2018-11-13 13:22:00 -08001229template <typename C1, typename C2, typename OutputIterator,
1230 typename = typename std::enable_if<
1231 !container_algorithm_internal::IsUnorderedContainer<C1>::value,
1232 void>::type,
1233 typename = typename std::enable_if<
1234 !container_algorithm_internal::IsUnorderedContainer<C2>::value,
1235 void>::type>
mistergc2e75482017-09-19 16:54:40 -04001236OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) {
1237 return std::set_union(container_algorithm_internal::c_begin(c1),
1238 container_algorithm_internal::c_end(c1),
1239 container_algorithm_internal::c_begin(c2),
1240 container_algorithm_internal::c_end(c2), output);
1241}
1242
1243// Overload of c_set_union() for performing a merge using a `comp` other than
1244// `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001245template <typename C1, typename C2, typename OutputIterator, typename LessThan,
Abseil Team7b46e1d2018-11-13 13:22:00 -08001246 typename = typename std::enable_if<
1247 !container_algorithm_internal::IsUnorderedContainer<C1>::value,
1248 void>::type,
1249 typename = typename std::enable_if<
1250 !container_algorithm_internal::IsUnorderedContainer<C2>::value,
1251 void>::type>
mistergc2e75482017-09-19 16:54:40 -04001252OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output,
Abseil Team1ae9b712021-04-20 07:17:48 -07001253 LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001254 return std::set_union(container_algorithm_internal::c_begin(c1),
1255 container_algorithm_internal::c_end(c1),
1256 container_algorithm_internal::c_begin(c2),
1257 container_algorithm_internal::c_end(c2), output,
Abseil Team1ae9b712021-04-20 07:17:48 -07001258 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001259}
1260
1261// c_set_intersection()
1262//
1263// Container-based version of the <algorithm> `std::set_intersection()` function
Abseil Team89c531c2021-07-29 08:04:56 -07001264// to return an iterator containing the intersection of two sorted containers.
Abseil Team7b46e1d2018-11-13 13:22:00 -08001265template <typename C1, typename C2, typename OutputIterator,
1266 typename = typename std::enable_if<
1267 !container_algorithm_internal::IsUnorderedContainer<C1>::value,
1268 void>::type,
1269 typename = typename std::enable_if<
1270 !container_algorithm_internal::IsUnorderedContainer<C2>::value,
1271 void>::type>
mistergc2e75482017-09-19 16:54:40 -04001272OutputIterator c_set_intersection(const C1& c1, const C2& c2,
1273 OutputIterator output) {
Abseil Team89c531c2021-07-29 08:04:56 -07001274 // In debug builds, ensure that both containers are sorted with respect to the
1275 // default comparator. std::set_intersection requires the containers be sorted
1276 // using operator<.
1277 assert(absl::c_is_sorted(c1));
1278 assert(absl::c_is_sorted(c2));
mistergc2e75482017-09-19 16:54:40 -04001279 return std::set_intersection(container_algorithm_internal::c_begin(c1),
1280 container_algorithm_internal::c_end(c1),
1281 container_algorithm_internal::c_begin(c2),
1282 container_algorithm_internal::c_end(c2), output);
1283}
1284
1285// Overload of c_set_intersection() for performing a merge using a `comp` other
1286// than `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001287template <typename C1, typename C2, typename OutputIterator, typename LessThan,
Abseil Team7b46e1d2018-11-13 13:22:00 -08001288 typename = typename std::enable_if<
1289 !container_algorithm_internal::IsUnorderedContainer<C1>::value,
1290 void>::type,
1291 typename = typename std::enable_if<
1292 !container_algorithm_internal::IsUnorderedContainer<C2>::value,
1293 void>::type>
mistergc2e75482017-09-19 16:54:40 -04001294OutputIterator c_set_intersection(const C1& c1, const C2& c2,
Abseil Team1ae9b712021-04-20 07:17:48 -07001295 OutputIterator output, LessThan&& comp) {
Abseil Team89c531c2021-07-29 08:04:56 -07001296 // In debug builds, ensure that both containers are sorted with respect to the
1297 // default comparator. std::set_intersection requires the containers be sorted
1298 // using the same comparator.
1299 assert(absl::c_is_sorted(c1, comp));
1300 assert(absl::c_is_sorted(c2, comp));
mistergc2e75482017-09-19 16:54:40 -04001301 return std::set_intersection(container_algorithm_internal::c_begin(c1),
1302 container_algorithm_internal::c_end(c1),
1303 container_algorithm_internal::c_begin(c2),
1304 container_algorithm_internal::c_end(c2), output,
Abseil Team1ae9b712021-04-20 07:17:48 -07001305 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001306}
1307
1308// c_set_difference()
1309//
1310// Container-based version of the <algorithm> `std::set_difference()` function
1311// to return an iterator containing elements present in the first container but
1312// not in the second.
Abseil Team7b46e1d2018-11-13 13:22:00 -08001313template <typename C1, typename C2, typename OutputIterator,
1314 typename = typename std::enable_if<
1315 !container_algorithm_internal::IsUnorderedContainer<C1>::value,
1316 void>::type,
1317 typename = typename std::enable_if<
1318 !container_algorithm_internal::IsUnorderedContainer<C2>::value,
1319 void>::type>
mistergc2e75482017-09-19 16:54:40 -04001320OutputIterator c_set_difference(const C1& c1, const C2& c2,
1321 OutputIterator output) {
1322 return std::set_difference(container_algorithm_internal::c_begin(c1),
1323 container_algorithm_internal::c_end(c1),
1324 container_algorithm_internal::c_begin(c2),
1325 container_algorithm_internal::c_end(c2), output);
1326}
1327
1328// Overload of c_set_difference() for performing a merge using a `comp` other
1329// than `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001330template <typename C1, typename C2, typename OutputIterator, typename LessThan,
Abseil Team7b46e1d2018-11-13 13:22:00 -08001331 typename = typename std::enable_if<
1332 !container_algorithm_internal::IsUnorderedContainer<C1>::value,
1333 void>::type,
1334 typename = typename std::enable_if<
1335 !container_algorithm_internal::IsUnorderedContainer<C2>::value,
1336 void>::type>
mistergc2e75482017-09-19 16:54:40 -04001337OutputIterator c_set_difference(const C1& c1, const C2& c2,
Abseil Team1ae9b712021-04-20 07:17:48 -07001338 OutputIterator output, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001339 return std::set_difference(container_algorithm_internal::c_begin(c1),
1340 container_algorithm_internal::c_end(c1),
1341 container_algorithm_internal::c_begin(c2),
1342 container_algorithm_internal::c_end(c2), output,
Abseil Team1ae9b712021-04-20 07:17:48 -07001343 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001344}
1345
1346// c_set_symmetric_difference()
1347//
1348// Container-based version of the <algorithm> `std::set_symmetric_difference()`
1349// function to return an iterator containing elements present in either one
1350// container or the other, but not both.
Abseil Team7b46e1d2018-11-13 13:22:00 -08001351template <typename C1, typename C2, typename OutputIterator,
1352 typename = typename std::enable_if<
1353 !container_algorithm_internal::IsUnorderedContainer<C1>::value,
1354 void>::type,
1355 typename = typename std::enable_if<
1356 !container_algorithm_internal::IsUnorderedContainer<C2>::value,
1357 void>::type>
mistergc2e75482017-09-19 16:54:40 -04001358OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
1359 OutputIterator output) {
1360 return std::set_symmetric_difference(
1361 container_algorithm_internal::c_begin(c1),
1362 container_algorithm_internal::c_end(c1),
1363 container_algorithm_internal::c_begin(c2),
1364 container_algorithm_internal::c_end(c2), output);
1365}
1366
1367// Overload of c_set_symmetric_difference() for performing a merge using a
1368// `comp` other than `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001369template <typename C1, typename C2, typename OutputIterator, typename LessThan,
Abseil Team7b46e1d2018-11-13 13:22:00 -08001370 typename = typename std::enable_if<
1371 !container_algorithm_internal::IsUnorderedContainer<C1>::value,
1372 void>::type,
1373 typename = typename std::enable_if<
1374 !container_algorithm_internal::IsUnorderedContainer<C2>::value,
1375 void>::type>
mistergc2e75482017-09-19 16:54:40 -04001376OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
1377 OutputIterator output,
Abseil Team1ae9b712021-04-20 07:17:48 -07001378 LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001379 return std::set_symmetric_difference(
1380 container_algorithm_internal::c_begin(c1),
1381 container_algorithm_internal::c_end(c1),
1382 container_algorithm_internal::c_begin(c2),
1383 container_algorithm_internal::c_end(c2), output,
Abseil Team1ae9b712021-04-20 07:17:48 -07001384 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001385}
1386
1387//------------------------------------------------------------------------------
1388// <algorithm> Heap functions
1389//------------------------------------------------------------------------------
1390
1391// c_push_heap()
1392//
1393// Container-based version of the <algorithm> `std::push_heap()` function
1394// to push a value onto a container heap.
1395template <typename RandomAccessContainer>
1396void c_push_heap(RandomAccessContainer& sequence) {
1397 std::push_heap(container_algorithm_internal::c_begin(sequence),
1398 container_algorithm_internal::c_end(sequence));
1399}
1400
1401// Overload of c_push_heap() for performing a push operation on a heap using a
1402// `comp` other than `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001403template <typename RandomAccessContainer, typename LessThan>
1404void c_push_heap(RandomAccessContainer& sequence, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001405 std::push_heap(container_algorithm_internal::c_begin(sequence),
1406 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -07001407 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001408}
1409
1410// c_pop_heap()
1411//
1412// Container-based version of the <algorithm> `std::pop_heap()` function
1413// to pop a value from a heap container.
1414template <typename RandomAccessContainer>
1415void c_pop_heap(RandomAccessContainer& sequence) {
1416 std::pop_heap(container_algorithm_internal::c_begin(sequence),
1417 container_algorithm_internal::c_end(sequence));
1418}
1419
1420// Overload of c_pop_heap() for performing a pop operation on a heap using a
1421// `comp` other than `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001422template <typename RandomAccessContainer, typename LessThan>
1423void c_pop_heap(RandomAccessContainer& sequence, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001424 std::pop_heap(container_algorithm_internal::c_begin(sequence),
1425 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -07001426 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001427}
1428
1429// c_make_heap()
1430//
1431// Container-based version of the <algorithm> `std::make_heap()` function
1432// to make a container a heap.
1433template <typename RandomAccessContainer>
1434void c_make_heap(RandomAccessContainer& sequence) {
1435 std::make_heap(container_algorithm_internal::c_begin(sequence),
1436 container_algorithm_internal::c_end(sequence));
1437}
1438
1439// Overload of c_make_heap() for performing heap comparisons using a
1440// `comp` other than `operator<`
Abseil Team1ae9b712021-04-20 07:17:48 -07001441template <typename RandomAccessContainer, typename LessThan>
1442void c_make_heap(RandomAccessContainer& sequence, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001443 std::make_heap(container_algorithm_internal::c_begin(sequence),
1444 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -07001445 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001446}
1447
1448// c_sort_heap()
1449//
1450// Container-based version of the <algorithm> `std::sort_heap()` function
1451// to sort a heap into ascending order (after which it is no longer a heap).
1452template <typename RandomAccessContainer>
1453void c_sort_heap(RandomAccessContainer& sequence) {
1454 std::sort_heap(container_algorithm_internal::c_begin(sequence),
1455 container_algorithm_internal::c_end(sequence));
1456}
1457
1458// Overload of c_sort_heap() for performing heap comparisons using a
1459// `comp` other than `operator<`
Abseil Team1ae9b712021-04-20 07:17:48 -07001460template <typename RandomAccessContainer, typename LessThan>
1461void c_sort_heap(RandomAccessContainer& sequence, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001462 std::sort_heap(container_algorithm_internal::c_begin(sequence),
1463 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -07001464 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001465}
1466
1467// c_is_heap()
1468//
1469// Container-based version of the <algorithm> `std::is_heap()` function
1470// to check whether the given container is a heap.
1471template <typename RandomAccessContainer>
1472bool c_is_heap(const RandomAccessContainer& sequence) {
1473 return std::is_heap(container_algorithm_internal::c_begin(sequence),
1474 container_algorithm_internal::c_end(sequence));
1475}
1476
1477// Overload of c_is_heap() for performing heap comparisons using a
1478// `comp` other than `operator<`
Abseil Team1ae9b712021-04-20 07:17:48 -07001479template <typename RandomAccessContainer, typename LessThan>
1480bool c_is_heap(const RandomAccessContainer& sequence, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001481 return std::is_heap(container_algorithm_internal::c_begin(sequence),
1482 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -07001483 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001484}
1485
1486// c_is_heap_until()
1487//
1488// Container-based version of the <algorithm> `std::is_heap_until()` function
1489// to find the first element in a given container which is not in heap order.
1490template <typename RandomAccessContainer>
1491container_algorithm_internal::ContainerIter<RandomAccessContainer>
1492c_is_heap_until(RandomAccessContainer& sequence) {
1493 return std::is_heap_until(container_algorithm_internal::c_begin(sequence),
1494 container_algorithm_internal::c_end(sequence));
1495}
1496
1497// Overload of c_is_heap_until() for performing heap comparisons using a
1498// `comp` other than `operator<`
Abseil Team1ae9b712021-04-20 07:17:48 -07001499template <typename RandomAccessContainer, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001500container_algorithm_internal::ContainerIter<RandomAccessContainer>
Abseil Team1ae9b712021-04-20 07:17:48 -07001501c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001502 return std::is_heap_until(container_algorithm_internal::c_begin(sequence),
1503 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -07001504 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001505}
1506
1507//------------------------------------------------------------------------------
1508// <algorithm> Min/max
1509//------------------------------------------------------------------------------
1510
1511// c_min_element()
1512//
1513// Container-based version of the <algorithm> `std::min_element()` function
1514// to return an iterator pointing to the element with the smallest value, using
1515// `operator<` to make the comparisons.
1516template <typename Sequence>
1517container_algorithm_internal::ContainerIter<Sequence> c_min_element(
1518 Sequence& sequence) {
1519 return std::min_element(container_algorithm_internal::c_begin(sequence),
1520 container_algorithm_internal::c_end(sequence));
1521}
1522
1523// Overload of c_min_element() for performing a `comp` comparison other than
1524// `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001525template <typename Sequence, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001526container_algorithm_internal::ContainerIter<Sequence> c_min_element(
Abseil Team1ae9b712021-04-20 07:17:48 -07001527 Sequence& sequence, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001528 return std::min_element(container_algorithm_internal::c_begin(sequence),
1529 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -07001530 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001531}
1532
1533// c_max_element()
1534//
1535// Container-based version of the <algorithm> `std::max_element()` function
1536// to return an iterator pointing to the element with the largest value, using
1537// `operator<` to make the comparisons.
1538template <typename Sequence>
1539container_algorithm_internal::ContainerIter<Sequence> c_max_element(
1540 Sequence& sequence) {
1541 return std::max_element(container_algorithm_internal::c_begin(sequence),
1542 container_algorithm_internal::c_end(sequence));
1543}
1544
1545// Overload of c_max_element() for performing a `comp` comparison other than
1546// `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001547template <typename Sequence, typename LessThan>
mistergc2e75482017-09-19 16:54:40 -04001548container_algorithm_internal::ContainerIter<Sequence> c_max_element(
Abseil Team1ae9b712021-04-20 07:17:48 -07001549 Sequence& sequence, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001550 return std::max_element(container_algorithm_internal::c_begin(sequence),
1551 container_algorithm_internal::c_end(sequence),
Abseil Team1ae9b712021-04-20 07:17:48 -07001552 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001553}
1554
1555// c_minmax_element()
1556//
1557// Container-based version of the <algorithm> `std::minmax_element()` function
1558// to return a pair of iterators pointing to the elements containing the
1559// smallest and largest values, respectively, using `operator<` to make the
1560// comparisons.
1561template <typename C>
Abseil Teamb8720b42023-01-23 11:51:06 -08001562container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
1563 C& c) {
mistergc2e75482017-09-19 16:54:40 -04001564 return std::minmax_element(container_algorithm_internal::c_begin(c),
1565 container_algorithm_internal::c_end(c));
1566}
1567
1568// Overload of c_minmax_element() for performing `comp` comparisons other than
1569// `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001570template <typename C, typename LessThan>
Abseil Teamb8720b42023-01-23 11:51:06 -08001571container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
1572 C& c, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001573 return std::minmax_element(container_algorithm_internal::c_begin(c),
1574 container_algorithm_internal::c_end(c),
Abseil Team1ae9b712021-04-20 07:17:48 -07001575 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001576}
1577
1578//------------------------------------------------------------------------------
1579// <algorithm> Lexicographical Comparisons
1580//------------------------------------------------------------------------------
1581
1582// c_lexicographical_compare()
1583//
1584// Container-based version of the <algorithm> `std::lexicographical_compare()`
1585// function to lexicographically compare (e.g. sort words alphabetically) two
1586// container sequences. The comparison is performed using `operator<`. Note
1587// that capital letters ("A-Z") have ASCII values less than lowercase letters
1588// ("a-z").
1589template <typename Sequence1, typename Sequence2>
Abseil Teamb8720b42023-01-23 11:51:06 -08001590bool c_lexicographical_compare(const Sequence1& sequence1,
1591 const Sequence2& sequence2) {
mistergc2e75482017-09-19 16:54:40 -04001592 return std::lexicographical_compare(
1593 container_algorithm_internal::c_begin(sequence1),
1594 container_algorithm_internal::c_end(sequence1),
1595 container_algorithm_internal::c_begin(sequence2),
1596 container_algorithm_internal::c_end(sequence2));
1597}
1598
1599// Overload of c_lexicographical_compare() for performing a lexicographical
1600// comparison using a `comp` operator instead of `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001601template <typename Sequence1, typename Sequence2, typename LessThan>
Abseil Teamb8720b42023-01-23 11:51:06 -08001602bool c_lexicographical_compare(const Sequence1& sequence1,
1603 const Sequence2& sequence2, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001604 return std::lexicographical_compare(
1605 container_algorithm_internal::c_begin(sequence1),
1606 container_algorithm_internal::c_end(sequence1),
1607 container_algorithm_internal::c_begin(sequence2),
1608 container_algorithm_internal::c_end(sequence2),
Abseil Team1ae9b712021-04-20 07:17:48 -07001609 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001610}
1611
1612// c_next_permutation()
1613//
1614// Container-based version of the <algorithm> `std::next_permutation()` function
1615// to rearrange a container's elements into the next lexicographically greater
1616// permutation.
1617template <typename C>
1618bool c_next_permutation(C& c) {
1619 return std::next_permutation(container_algorithm_internal::c_begin(c),
1620 container_algorithm_internal::c_end(c));
1621}
1622
1623// Overload of c_next_permutation() for performing a lexicographical
1624// comparison using a `comp` operator instead of `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001625template <typename C, typename LessThan>
1626bool c_next_permutation(C& c, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001627 return std::next_permutation(container_algorithm_internal::c_begin(c),
1628 container_algorithm_internal::c_end(c),
Abseil Team1ae9b712021-04-20 07:17:48 -07001629 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001630}
1631
1632// c_prev_permutation()
1633//
1634// Container-based version of the <algorithm> `std::prev_permutation()` function
1635// to rearrange a container's elements into the next lexicographically lesser
1636// permutation.
1637template <typename C>
1638bool c_prev_permutation(C& c) {
1639 return std::prev_permutation(container_algorithm_internal::c_begin(c),
1640 container_algorithm_internal::c_end(c));
1641}
1642
1643// Overload of c_prev_permutation() for performing a lexicographical
1644// comparison using a `comp` operator instead of `operator<`.
Abseil Team1ae9b712021-04-20 07:17:48 -07001645template <typename C, typename LessThan>
1646bool c_prev_permutation(C& c, LessThan&& comp) {
mistergc2e75482017-09-19 16:54:40 -04001647 return std::prev_permutation(container_algorithm_internal::c_begin(c),
1648 container_algorithm_internal::c_end(c),
Abseil Team1ae9b712021-04-20 07:17:48 -07001649 std::forward<LessThan>(comp));
mistergc2e75482017-09-19 16:54:40 -04001650}
1651
1652//------------------------------------------------------------------------------
1653// <numeric> algorithms
1654//------------------------------------------------------------------------------
1655
1656// c_iota()
1657//
Abseil Teama09d2102022-11-22 06:36:17 -08001658// Container-based version of the <numeric> `std::iota()` function
mistergc2e75482017-09-19 16:54:40 -04001659// to compute successive values of `value`, as if incremented with `++value`
1660// after each element is written. and write them to the container.
1661template <typename Sequence, typename T>
Abseil Teamb8720b42023-01-23 11:51:06 -08001662void c_iota(Sequence& sequence, const T& value) {
mistergc2e75482017-09-19 16:54:40 -04001663 std::iota(container_algorithm_internal::c_begin(sequence),
Abseil Teamb8720b42023-01-23 11:51:06 -08001664 container_algorithm_internal::c_end(sequence), value);
mistergc2e75482017-09-19 16:54:40 -04001665}
Abseil Teamb8720b42023-01-23 11:51:06 -08001666
mistergc2e75482017-09-19 16:54:40 -04001667// c_accumulate()
1668//
Abseil Teama09d2102022-11-22 06:36:17 -08001669// Container-based version of the <numeric> `std::accumulate()` function
mistergc2e75482017-09-19 16:54:40 -04001670// to accumulate the element values of a container to `init` and return that
1671// accumulation by value.
1672//
1673// Note: Due to a language technicality this function has return type
1674// absl::decay_t<T>. As a user of this function you can casually read
1675// this as "returns T by value" and assume it does the right thing.
1676template <typename Sequence, typename T>
1677decay_t<T> c_accumulate(const Sequence& sequence, T&& init) {
1678 return std::accumulate(container_algorithm_internal::c_begin(sequence),
1679 container_algorithm_internal::c_end(sequence),
1680 std::forward<T>(init));
1681}
1682
1683// Overload of c_accumulate() for using a binary operations other than
1684// addition for computing the accumulation.
1685template <typename Sequence, typename T, typename BinaryOp>
1686decay_t<T> c_accumulate(const Sequence& sequence, T&& init,
1687 BinaryOp&& binary_op) {
1688 return std::accumulate(container_algorithm_internal::c_begin(sequence),
1689 container_algorithm_internal::c_end(sequence),
1690 std::forward<T>(init),
1691 std::forward<BinaryOp>(binary_op));
1692}
1693
1694// c_inner_product()
1695//
Abseil Teama09d2102022-11-22 06:36:17 -08001696// Container-based version of the <numeric> `std::inner_product()` function
mistergc2e75482017-09-19 16:54:40 -04001697// to compute the cumulative inner product of container element pairs.
1698//
1699// Note: Due to a language technicality this function has return type
1700// absl::decay_t<T>. As a user of this function you can casually read
1701// this as "returns T by value" and assume it does the right thing.
1702template <typename Sequence1, typename Sequence2, typename T>
1703decay_t<T> c_inner_product(const Sequence1& factors1, const Sequence2& factors2,
1704 T&& sum) {
1705 return std::inner_product(container_algorithm_internal::c_begin(factors1),
1706 container_algorithm_internal::c_end(factors1),
1707 container_algorithm_internal::c_begin(factors2),
1708 std::forward<T>(sum));
1709}
1710
1711// Overload of c_inner_product() for using binary operations other than
Bruce Mitchener08760ad2018-04-20 01:11:44 +07001712// `operator+` (for computing the accumulation) and `operator*` (for computing
mistergc2e75482017-09-19 16:54:40 -04001713// the product between the two container's element pair).
1714template <typename Sequence1, typename Sequence2, typename T,
1715 typename BinaryOp1, typename BinaryOp2>
1716decay_t<T> c_inner_product(const Sequence1& factors1, const Sequence2& factors2,
1717 T&& sum, BinaryOp1&& op1, BinaryOp2&& op2) {
1718 return std::inner_product(container_algorithm_internal::c_begin(factors1),
1719 container_algorithm_internal::c_end(factors1),
1720 container_algorithm_internal::c_begin(factors2),
1721 std::forward<T>(sum), std::forward<BinaryOp1>(op1),
1722 std::forward<BinaryOp2>(op2));
1723}
1724
1725// c_adjacent_difference()
1726//
Abseil Teama09d2102022-11-22 06:36:17 -08001727// Container-based version of the <numeric> `std::adjacent_difference()`
mistergc2e75482017-09-19 16:54:40 -04001728// function to compute the difference between each element and the one preceding
1729// it and write it to an iterator.
1730template <typename InputSequence, typename OutputIt>
1731OutputIt c_adjacent_difference(const InputSequence& input,
1732 OutputIt output_first) {
1733 return std::adjacent_difference(container_algorithm_internal::c_begin(input),
1734 container_algorithm_internal::c_end(input),
1735 output_first);
1736}
1737
1738// Overload of c_adjacent_difference() for using a binary operation other than
1739// subtraction to compute the adjacent difference.
1740template <typename InputSequence, typename OutputIt, typename BinaryOp>
1741OutputIt c_adjacent_difference(const InputSequence& input,
1742 OutputIt output_first, BinaryOp&& op) {
1743 return std::adjacent_difference(container_algorithm_internal::c_begin(input),
1744 container_algorithm_internal::c_end(input),
1745 output_first, std::forward<BinaryOp>(op));
1746}
1747
1748// c_partial_sum()
1749//
Abseil Teama09d2102022-11-22 06:36:17 -08001750// Container-based version of the <numeric> `std::partial_sum()` function
mistergc2e75482017-09-19 16:54:40 -04001751// to compute the partial sum of the elements in a sequence and write them
1752// to an iterator. The partial sum is the sum of all element values so far in
1753// the sequence.
1754template <typename InputSequence, typename OutputIt>
1755OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first) {
1756 return std::partial_sum(container_algorithm_internal::c_begin(input),
1757 container_algorithm_internal::c_end(input),
1758 output_first);
1759}
1760
1761// Overload of c_partial_sum() for using a binary operation other than addition
1762// to compute the "partial sum".
1763template <typename InputSequence, typename OutputIt, typename BinaryOp>
1764OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first,
1765 BinaryOp&& op) {
1766 return std::partial_sum(container_algorithm_internal::c_begin(input),
1767 container_algorithm_internal::c_end(input),
1768 output_first, std::forward<BinaryOp>(op));
1769}
1770
Abseil Team12bc53e2019-12-12 10:36:03 -08001771ABSL_NAMESPACE_END
mistergc2e75482017-09-19 16:54:40 -04001772} // namespace absl
1773
1774#endif // ABSL_ALGORITHM_CONTAINER_H_