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