File: algorithms.qbk

package info (click to toggle)
boost1.74 1.74.0%2Bds1-21
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 463,588 kB
  • sloc: cpp: 3,338,117; xml: 131,293; python: 33,088; ansic: 14,292; asm: 4,038; sh: 3,353; makefile: 1,193; perl: 1,036; yacc: 478; php: 212; ruby: 102; lisp: 24; sql: 13; csh: 6
file content (182 lines) | stat: -rw-r--r-- 6,667 bytes parent folder | download | duplicates (13)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
[/
    Copyright 2010 Neil Groves
    Distributed under the Boost Software License, Version 1.0.
    (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:algorithms Range Algorithms]
[section:introduction Introduction and motivation]
In its most simple form a [*Range Algorithm] (or range-based algorithm) is simply an iterator-based algorithm where the /two/ iterator arguments have been replaced by /one/ range argument. For example, we may write

``
#include <boost/range/algorithm.hpp>
#include <vector>

std::vector<int> vec = ...;
boost::sort(vec);
``

instead of

``
std::sort(vec.begin(), vec.end());
``

However, the return type of range algorithms is almost always different from that of existing iterator-based algorithms.

One group of algorithms, like `boost::sort()`, will simply return the same range so that we can continue to pass the range around and/or further modify it. Because of this we may write
``
boost:unique(boost::sort(vec));
``
to first sort the range and then run `unique()` on the sorted range.

Algorithms like `boost::unique()` fall into another group of algorithms that return (potentially) narrowed views of the original range. By default `boost::unique(rng)` returns the range `[boost::begin(rng), found)` where `found` denotes the iterator returned by `std::unique(boost::begin(rng), boost::end(rng))`

Therefore exactly the unique values can be copied by writing
``
boost::copy(boost::unique(boost::sort(vec)),
            std::ostream_iterator<int>(std::cout));
``

Algorithms like `boost::unique` usually return the range: `[boost::begin(rng), found)`.
However, this behaviour may be changed by supplying a `range_return_value`
as a template parameter to the algorithm:

[table
    [[Expression] [Return]]
    [[`boost::unique<boost::return_found>(rng)`] [returns a single iterator like `std::unique`]]
    [[`boost::unique<boost::return_begin_found>(rng)`] [returns the range `[boost::begin(rng), found)` (this is the default)]]
    [[`boost::unique<boost::return_begin_next>(rng)`] [returns the range `[boost::begin(rng), boost::next(found))`]]
    [[`boost::unique<boost::return_found_end>(rng)`] [returns the range `[found, boost::end(rng))`]]
    [[`boost::unique<boost::return_next_end>(rng)`] [returns the range `[boost::next(found),boost::end(rng))`]]
    [[`boost::unique<boost::return_begin_end>(rng)`] [returns the entire original range.]]
]

This functionality has the following advantages:

# it allows for ['*seamless functional-style programming*] where you do not need to use named local variables to store intermediate results
# it is very ['*safe*] because the algorithm can verify out-of-bounds conditions and handle tricky conditions that lead to empty ranges

For example, consider how easy we may erase the duplicates in a sorted container:

``
std::vector<int> vec = ...;
boost::erase(vec, boost::unique<boost::return_found_end>(boost::sort(vec)));
``

Notice the use of `boost::return_found_end`. What if we wanted to erase all the duplicates except one of them? In old-fashioned STL-programming we might write

``
// assume 'vec' is already sorted
std::vector<int>::iterator i = std::unique(vec.begin(), vec.end());

// remember this check or you get into problems
if (i != vec.end())
    ++i;

vec.erase(i, vec.end());
``

The same task may be accomplished simply with
``
boost::erase(vec, boost::unique<boost::return_next_end>(vec));
``
and there is no need to worry about generating an invalid range. Furthermore, if the container is complex, calling `vec.end()` several times will be more expensive than using a range algorithm.

[endsect]

[section:mutating Mutating algorithms]
[include algorithm/copy.qbk]
[include algorithm/copy_backward.qbk]
[include algorithm/fill.qbk]
[include algorithm/fill_n.qbk]
[include algorithm/generate.qbk]
[include algorithm/inplace_merge.qbk]
[include algorithm/merge.qbk]
[include algorithm/nth_element.qbk]
[include algorithm/partial_sort.qbk]
[include algorithm/partition.qbk]
[include algorithm/random_shuffle.qbk]
[include algorithm/remove.qbk]
[include algorithm/remove_copy.qbk]
[include algorithm/remove_copy_if.qbk]
[include algorithm/remove_if.qbk]
[include algorithm/replace.qbk]
[include algorithm/replace_copy.qbk]
[include algorithm/replace_copy_if.qbk]
[include algorithm/replace_if.qbk]
[include algorithm/reverse.qbk]
[include algorithm/reverse_copy.qbk]
[include algorithm/rotate.qbk]
[include algorithm/rotate_copy.qbk]
[include algorithm/sort.qbk]
[include algorithm/stable_partition.qbk]
[include algorithm/stable_sort.qbk]
[include algorithm/swap_ranges.qbk]
[include algorithm/transform.qbk]
[include algorithm/unique.qbk]
[include algorithm/unique_copy.qbk]
[endsect]

[section:non_mutating Non-mutating algorithms]
[include algorithm/adjacent_find.qbk]
[include algorithm/binary_search.qbk]
[include algorithm/count.qbk]
[include algorithm/count_if.qbk]
[include algorithm/equal.qbk]
[include algorithm/equal_range.qbk]
[include algorithm/for_each.qbk]
[include algorithm/find.qbk]
[include algorithm/find_end.qbk]
[include algorithm/find_first_of.qbk]
[include algorithm/find_if.qbk]
[include algorithm/lexicographical_compare.qbk]
[include algorithm/lower_bound.qbk]
[include algorithm/max_element.qbk]
[include algorithm/min_element.qbk]
[include algorithm/mismatch.qbk]
[include algorithm/search.qbk]
[include algorithm/search_n.qbk]
[include algorithm/upper_bound.qbk]
[endsect]

[section:set Set algorithms]
[include algorithm/includes.qbk]
[include algorithm/set_union.qbk]
[include algorithm/set_intersection.qbk]
[include algorithm/set_difference.qbk]
[include algorithm/set_symmetric_difference.qbk]
[endsect]

[section:heap Heap algorithms]
[include algorithm/push_heap.qbk]
[include algorithm/pop_heap.qbk]
[include algorithm/make_heap.qbk]
[include algorithm/sort_heap.qbk]
[endsect]

[section:permutation Permutation algorithms]
[include algorithm/next_permutation.qbk]
[include algorithm/prev_permutation.qbk]
[endsect]

[section:new New algorithms]
[include algorithm_ext/copy_n.qbk]
[include algorithm_ext/erase.qbk]
[include algorithm_ext/for_each.qbk]
[include algorithm_ext/insert.qbk]
[include algorithm_ext/iota.qbk]
[include algorithm_ext/is_sorted.qbk]
[include algorithm_ext/overwrite.qbk]
[include algorithm_ext/push_back.qbk]
[include algorithm_ext/push_front.qbk]
[include algorithm_ext/remove_erase.qbk]
[include algorithm_ext/remove_erase_if.qbk]
[endsect]

[section:numeric Numeric algorithms]
[include numeric/accumulate.qbk]
[include numeric/adjacent_difference.qbk]
[include numeric/inner_product.qbk]
[include numeric/partial_sum.qbk]
[endsect]
[endsect]