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