0% found this document useful (0 votes)
30 views

STL Algorithms in Action - Michael VanLoon - CppCon 2015

Uploaded by

alan88w
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views

STL Algorithms in Action - Michael VanLoon - CppCon 2015

Uploaded by

alan88w
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 99

STL Algorithms in Action

STL Algorithms and their


everyday application

Michael VanLoon
CPPcon 2015
What are algorithms?
al·go·rithm
noun: algorithm; plural noun: algorithms
A procedure for solving a … problem (as of
finding the greatest common divisor) in a finite
number of steps that frequently involves
repetition of an operation; broadly: a step-by-
step procedure for solving a problem or
accomplishing some end especially by a
computer.
Merriam-Webster dictionary

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 2


What are STL algorithms?
• A pre-built library of general-purpose algorithms
designed to solve specific problems
• Come “for free” with your C++ compiler
• Operate on sequences or sequenced containers
• Declarative in syntax – no explicit (“raw”) loops
• Iterate over some or all members of a sequence
performing an operation on each element in turn
• Designed by experts and proven bug-free by the
millions of lines of other peoples’ programs that
already use them!
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 3
What is a raw loop anyway?
• It’s a for, while, or do… while loop
• Explicitly coded
• Often contains many lines of code (should it?)
• May cause side-effects outside its scope

vector<int> out;
bool found = false;
for (const auto& i: v) {
if (i >= 42) {
out.emplace_back(i);
++global_count;
if (i == 42) {
found = true;
}
}
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 4


Why use algorithms?
• Often more efficient than hand-written loop
• Cleaner and more clearly abstracted than a
raw loop
• Contains side-effects inside a clear interface
• Prevents accidental leakage of side-effects
• Eases reasoning about functionality and
reasoning about post conditions
• Less likely to fail under non-obvious conditions
• Eases reasoning about the surrounding code
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 5
Classes of STL algorithms
• Non-modifying sequence operations (25.2)
• Mutating sequence operations (25.3)
• Sorting and related operations (25.4)
• General C algorithms (25.5)
• General numeric operations (26.7)
(section of the C++ standard INCITS/ISO/IEC 14882-2011[2012])

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 6


STL algorithms
non-modifying sequence operations

• Do not modify the input sequence.


• Do not emit a result sequence.
• Algorithm will not cause side-effects in
input sequence.
• Function object, if present, may cause side-
effects by modifying itself, the sequence (in
certain cases, e.g. for_each), or its
environment.
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 7
STL algorithms
non-modifying sequence operations
• all_of • adjacent_find
• any_of • count
• none_of – count_if
• for_each • mismatch
• find • equal
– find_if • is_permutation
– find_if_not • search
• find_end – search_n
• find_first_of
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 8
STL algorithms
mutating sequence operations
• Do not modify the input sequence, except in situations
when output overlaps input, resulting in modification in-
place (e.g. transform).
• Emit an output sequence of results.
• Output sequence may potentially overlap input
sequence for certain algorithms (e.g. transform).
Others (e.g. copy) explicitly disallow overlap/in-place.
• Algorithm will explicitly cause side-effects in output
sequence.
• Function object, if present, may cause side-effects by
modifying itself or its environment. Function object
should not modify the input or output sequences.

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 9


STL algorithms
mutating sequence operations
• copy • remove
– copy_n – remove_if
– copy_if – remove_copy
– copy_backward – remove_copy_if
• move • unique
– move_backward – unique_copy
• swap_ranges • reverse
– iter_swap – reverse_copy
• transform • rotate
• replace – rotate_copy
– replace_if • shuffle
– replace_copy – random_shuffle
– replace_copy_if • partition
• fill – is_partitioned
– fill_n – stable_partition
• generate – partition_copy
– generate_n – partition_point

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 10


STL algorithms
sorting and related operations
• A mix of non-modifying and mutating
operations
• Mutating operations modify sequences in
place (e.g. sort, make_heap), or emit output
to an output sequence (e.g. merge,
partial_sort_copy)
• Default compare function is operator<
• Explicit compare function object, if supplied,
must not modify the sequence or iterators

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 11


STL algorithms
sorting and related operations
• sorting • heap operations
– sort – push_heap
– stable_sort – pop_heap
– partial_sort – make_heap
– partial_sort_copy – sort_heap
• nth_element • minimum and maximum
• binary search – min
– lower_bound – max
– upper_bound – minmax
– equal_range – min_element
– binary_search – max_element
• merge – minmax_element
– merge • lexicographical comparisons
– inplace_merge – lexicographical_compare
• set operations on sorted • permutation generators
structures – next_permutation
– includes – prev_permutation
– set_union
– set_intersection
– set_difference
– set_symmetric_difference

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 12


STL algorithms
general numeric operations
• Library of algorithms for doing numeric
operations.
• Consist of components for complex number
types, random number generation, nu- meric
(n-at-a-time) arrays, generalized numeric
algorithms, and facilities included from the ISO
C library.1
1Description from the standard library that is surprisingly understandable
by humans.

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 13


STL algorithms
general numeric operations

• accumulate
• inner_product
• partial_sum
• adjacent_difference
• iota

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 14


STL algorithms
C library algorithms

• These are shown for completeness.


• You may need to know about these for
legacy reasons.
• In general, there is nothing these can do
that you can’t do better with the modern
algorithms previously mentioned.

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 15


STL algorithms
C library algorithms

• bsearch
• qsort

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 16


for_each and transform
• Your go-to generic algorithms for doing
general things to sequences
• Applies an operation to each element in a
sequence, in order
• Very similar except completely different

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 17


for_each
• Applies an operation to each element in a sequence (like many
algorithms)
• Is a non-modifying sequence operation
• Algorithm produces no side-effect
• Function object may produce a side-effect by modifying the
input sequence
• Function object may produce a side-effect by modifying itself
• Returns a moved copy of the function object
• for_each is considered non-modifying because it produces
no output range; it relies on the function object for mutation, if
any

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 18


transform
• Applies an operation to each element in a sequence (like many
algorithms)
• Is a mutating sequence operation
• If the input range(s) and result range are the same, or overlap,
mutates objects in-place
• Algorithm explicitly produces a side-effect
• Function object may not produce a side-effect
• transform is considered mutating because it explicitly
produces an output range modified by applying the function
object to elements, and forbids the function object from
modifying any of the range elements or iterators
• Returns iterator pointing one past last element in result range
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 19
for_each example
Generate a single hash for all strings in a vector
struct HashString {
void operator()(const string& s) {
hash = accumulate(s.begin(), s.end(), hash, hash_char);
}
uint32_t hash = 0;
};

template<typename Cont>
uint32_t hash_all_strings(const Cont& v) {
auto hasher = for_each(v.begin(), v.end(), HashString());
return hasher.hash;
}

void test_for_each_hash() {
vector<string> v{ "one", "two", "three", "four", "five" };
uint32_t hash = hash_all_strings(v);
cout << "Hash: " << hash << dec << endl;
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 20


accumulate
• Is a non-modifying numerics operation
• Algorithm produces no side-effect
• Function object may not modify the sequence or the iterator
• Function object may produce a side-effect by returning a return
code different from input parameter
• accumulate differs from for_each in that the algorithm
carries a value rather than a function object from visit to visit,
applying the operation to each element and the current value
• accumulate differs from for_each in that it has a default
operation: operator+

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 21


for_each example
Generate a single hash for all strings in a vector
struct HashString {
void operator()(const string& s) {
hash = accumulate(s.begin(), s.end(), hash, hash_char);
}
uint32_t hash = 0;
};

template<typename Cont>
uint32_t hash_all_strings(const Cont& v) {
auto hasher = for_each(v.begin(), v.end(), HashString());
return hasher.hash;
}

void test_for_each_hash() {
vector<string> v{ "one", "two", "three", "four", "five" };
uint32_t hash = hash_all_strings(v);
cout << "Hash: " << hash << dec << endl;
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 22


for_each example
Generate a single hash for all strings in a vector
struct HashString {
void operator()(const string& s) {
hash = accumulate(s.begin(), s.end(), hash, hash_char);
}
uint32_t hash = 0;
};

template<typename Cont>
uint32_t hash_all_strings(const Cont& v) {
const auto hasher = for_each(v.begin(), v.end(), HashString());
return hasher.hash;
}

void test_for_each_hash() {
vector<string> v{ "one", "two", "three", "four", "five" };
uint32_t hash = hash_all_strings(v);
cout << "Hash: " << hash << dec << endl;
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 23


for_each example
Generate a single hash for all strings in a vector
struct HashString {
void operator()(const string& s) {
hash = accumulate(s.begin(), s.end(), hash, hash_char);
}
uint32_t hash = 0;
};

template<typename Cont>
uint32_t hash_all_strings(const Cont& v) {
const auto hasher = for_each(v.begin(), v.end(), HashString());
return hasher.hash;
}

void test_for_each_hash() {
vector<string> v{ "one", "two", "three", "four", "five" };
uint32_t hash = hash_all_strings(v);
cout << "Hash: " << hash << dec << endl;
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 24


for_each example (cont)
… the rest of the code…
uint32_t rotl(uint32_t value, unsigned int count) {
const uint32_t mask =
(CHAR_BIT * sizeof(value) - 1);
count &= mask;
return (value << count) |
(value >> ((-count)&mask));
}

uint32_t hash_char(uint32_t hash, char c)


{
hash = rotl(hash, c); // circular rotate left
hash ^= c;
return hash;
}
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 25
transform example
Generate hash for each string in a vector
uint32_t hash_string(const string& s) {
return accumulate(s.begin(), s.end(), 0, hash_char);
};

template<typename Cont>
vector<uint32_t> hash_each_string(const Cont& v) {
vector<uint32_t> res;
transform(v.begin(), v.end(), back_inserter(res), hash_string);
return res;
}

void test_transform_hash() {
vector<string> v{ "one", "two", "three", "four", "five" };
auto res = hash_each_string(v);
cout << "Hashes: ";
for_each(res.begin(), res.end(),
[](uint32_t rh){ cout << rh << " "; });
cout << endl;
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 26


transform example
Generate hash for each string in a vector
uint32_t hash_string(const string& s) {
return accumulate(s.begin(), s.end(), 0, hash_char);
};

template<typename Cont>
vector<uint32_t> hash_each_string(const Cont& v) {
vector<uint32_t> res;
transform(v.begin(), v.end(), back_inserter(res), hash_string);
return res;
}

void test_transform_hash() {
vector<string> v{ "one", "two", "three", "four", "five" };
auto res = hash_each_string(v);
cout << "Hashes: ";
for_each(res.begin(), res.end(),
[](uint32_t rh){ cout << rh << " "; });
cout << endl;
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 27


transform example
Generate hash for each string in a vector
uint32_t hash_string(const string& s) {
return accumulate(s.begin(), s.end(), 0, hash_char);
};

template<typename Cont>
vector<uint32_t> hash_each_string(const Cont& v) {
vector<uint32_t> res;
transform(v.begin(), v.end(), back_inserter(res), hash_string);
return res;
}

void test_transform_hash() {
vector<string> v{ "one", "two", "three", "four", "five" };
auto res = hash_each_string(v);
cout << "Hashes: ";
for_each(res.begin(), res.end(),
[](uint32_t rh){ cout << rh << " "; });
cout << endl;
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 28


any_of, all_of, and none_of
• Apply a function object to a sequence
• Determines whether any, all, or none of the
elements in the sequence are true as
determined by the function object
• May return before evaluating all elements
in sequence if outcome is determined early

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 29


all_of example
validate http headers
static const regex
reHeader("([A-Za-z0-9!#$%&'*+.^_`|~-]+): *(.+) *");

inline bool
headers_valid(const vector<string>& headers) {
return all_of(headers.begin(), headers.end(),
[](const auto& header) -> bool {
smatch matches;
return regex_match(header, matches, reHeader);
}
);
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 30


all_of example
validate http headers test and output
void all_of_headers() {
vector<string> h1 = { "Foo: bar", "Content-type: application/json",
"Accept: text/html,text/json,application/json" };
cout << "headers valid: " << boolalpha << headers_valid(h1) << endl;

vector<string> h2 = { "Foo : bar", "Content-type: application/json",


"Accept: text/html,text/json,application/json" };
cout << "headers valid: " << boolalpha << headers_valid(h2) << endl;

vector<string> h3 = { "Foo: bar", "Content-type: application/json",


":Accept: text/html,text/json,application/json" };
cout << "headers valid: " << boolalpha << headers_valid(h3) << endl;

vector<string> h4 = { "Foo: bar", " Content-type: application/json"


"Accept: text/html,text/json,application/json" };
cout << "headers valid: " << boolalpha << headers_valid(h4) << endl;
}

output:
headers valid: true
headers valid: false
headers valid: false
headers valid: false

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 31


any_of example
http header search
inline bool
header_search(const vector<string>& headers,
const string& find_header, const string& find_value)
{
return any_of(headers.begin(), headers.end(),
[&find_header, &find_value](const auto& header) -> bool {
const regex reHeader(
"(" + find_header + "): *(" + find_value + ") *",
regex::icase);
smatch matches;
return regex_match(header, matches, reHeader);
}
);
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 32


any_of example
http header search test and output
void any_of_headers_simple() {
vector<string> h1 = { "Foo: bar", "Content-type: application/json",
"X-SuperPower: toestrength",
"Accept: text/html,text/json,application/json" };
cout << "headers valid: " << boolalpha
<< header_search(h1, "X-SuperPower", "toestrength") << endl;

vector<string> h2 = { "Foo: bar", "Content-type: application/json",


"X-SuperPower: supersmell",
"Accept: text/html,text/json,application/json" };
cout << "headers valid: " << boolalpha
<< header_search(h2, "X-SuperPower", "toestrength") << endl;

vector<string> h3 = { "Foo : bar", "Content-type: application/json",


"X-SuperPower: toestrength",
"Accept: text/html,text/json,application/json" };
cout << "headers valid: " << boolalpha
<< header_search(h3, "X-Superpower", "toeStrength") << endl;
}

output:
headers valid: true
headers valid: false
headers valid: true

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 33


another for_each example
simultaneously validate and search http headers
struct HeaderData {
int good_headers = 0;
int bad_headers = 0;
multimap<string, string> found_headers;

string find_header;
string find_value;

operator bool() const { return !bad_headers && good_headers > 0; }

void operator() (const string& header) {


static const regex reValid("([A-Za-z0-9!#$%&'*+.^_`|~-]+): *(.+) *");
smatch matches;
bool match = regex_match(header, matches, reValid);
if (match) {
++good_headers;
const regex reHeader("(" + find_header + "): *(" + find_value + ") *", regex::icase);
if (regex_match(header, matches, reHeader)) {
found_headers.emplace(matches[1], matches[2]);
}
} else {
++bad_headers;
}
}
};

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 34


another for_each example
simultaneously validate and search http headers
struct HeaderData {
int good_headers = 0;
int bad_headers = 0;
multimap<string, string> found_headers;

string find_header;
string find_value;

operator bool() const;


void operator() (const string& header);
};

const HeaderData header_parse(const vector<string>& headers, const string&


find_header, const string& find_value) {
HeaderData hd;
hd.find_header = find_header;
hd.find_value = find_value;
return for_each(headers.begin(), headers.end(), hd);
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 35


another for_each example
simultaneous validate/search test
void any_of_headers_full() {
{
vector<string> h1 = { "Foo: bar", "Content-type: application/json", "X-SuperPower: toestrength",
"Accept: text/html,text/json,application/json" };
const HeaderData& hd = header_parse(h1, "X-SuperPower", "toestrength");
cout << "headers parse: " << hd << ", good " << hd.good_headers << ", bad " << hd.bad_headers;
for_each(hd.found_headers.begin(), hd.found_headers.end(), [](const auto& val) {
cout << "\n\t'" << val.first << "', '" << val.second << "'";
});
cout << endl;
}

{
vector<string> h2 = { "Foo: bar", "Content-type: application/json", "X-SuperPower: supersmell", "Accept: text/ht
ml,text/json,application/json" };
const HeaderData& hd = header_parse(h2, "X-SuperPower", "toestrength");
cout << "headers parse: " << hd << ", good " << hd.good_headers << ", bad " << hd.bad_headers;
for_each(hd.found_headers.begin(), hd.found_headers.end(), [](const auto& val) {
cout << "\n\t'" << val.first << "', '" << val.second << "'";
});
cout << endl;
}

{
vector<string> h3 = { "Foo : bar", "Content-type: application/json", "X-Superpower: toestrength", "Accept: text/
html,text/json,application/json" };
const HeaderData& hd = header_parse(h3, "X-SuperPower", "toestrength");
cout << "headers parse: " << hd << ", good " << hd.good_headers << ", bad " << hd.bad_headers;
for_each(hd.found_headers.begin(), hd.found_headers.end(), [](const auto& val) {
cout << "\n\t'" << val.first << "', '" << val.second << "'";
});
cout << endl;
}
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 36


another for_each example
simultaneous validate/search output
output:
headers parse: true, good 4, bad 0
'X-SuperPower', 'toestrength'
headers parse: true, good 4, bad 0
headers parse: false, good 3, bad 1
'X-Superpower', 'toestrength'

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 37


adjacent_find
• adjacent_find searches for adjacent items
(pairs of elements next to each other) in a
sequence that meet a certain condition.
• Returns an iterator to the first of the pair of
elements meeting the condition.
• The default condition is equality (i.e. find two
adjacent items that are equal).
• A custom comparator may be provided to look
for other adjacent conditions.

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 38


adjacent_find example
simple is_sorted implementation
vecInt_t v{ 1, 2, 3, 4, 5, 5, 6, 7, 8 };

// Greater works because it's asking if the first value is


// greater than the second value. If so, then the test
// fails (not sorted). If the first value is less than or
// equal to the second value, no match and success.
vecInt_t::iterator it =
adjacent_find(v.begin(), v.end(), greater<int>());

if (it == v.end())
cout << "Vector is sorted" << endl;
else
cout << "Vector not sorted, value " << *(it + 1)
<< ", at position " << it - v.begin() + 1 << endl;

output:
Vector is sorted
Vector not sorted, value 3, at position 9

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 39


adjacent_find example
test for sequence deviation
template<typename Cont>
typename Cont::const_iterator checkDeviation(const Cont& cont,
double allowed_dev)
{
return adjacent_find(cont.begin(), cont.end(),
[allowed_dev](const typename
Cont::value_type& v1,
const typename
Cont::value_type& v2)
{
auto limit = v1 * allowed_dev;
return (v2 > v1 + limit) ||
(v2 < v1 - limit);
});
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 40


adjacent_find example
test for sequence deviation test and output
vecDbl_t v{ 1.0, 1.05, 1.06, 1.04, 1.09, 1.15, 1.2 };

vecDbl_t::const_iterator it = checkDeviation(v, 0.1);


if (it == v.end())
cout << "Vector is within deviation limits" << endl;
else
cout << "Vector outside deviation limits, values " << *it << " and ”
<< *(it + 1) << ", at position " << it - v.begin() + 1 << endl;

v.push_back(2.0);

it = checkDeviation(v, 0.1);
if (it == v.end())
cout << "Vector is within deviation limits" << endl;
else
cout << "Vector outside deviation limits, values " << *it << " and ”
<< *(it + 1) << ", at position " << it - v.begin() + 1 << endl;

output:
Vector is within deviation limits
Vector outside deviation limits, values 1.2 and 2, at position 7

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 41


remove_if (with erase)
Scott Meyers, “Effective STL,” items 9 and 32

• Scenario: you want to erase several items


from a container that meet a condition
• You could write a loop with some checks,
some explicit erases, and potential iterator
invalidation
• Or…

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 42


remove_if (with erase)
Scott Meyers, “Effective STL,” items 9 and 32
struct Foo {
bool expired;
… other members…
};

vector<Foo> v;

v.erase(
remove_if(v.begin(), v.end(),
[](const Foo& foo){ return foo.expired; }),
v.end());

Output:
before: [val: 1, expired: false] [val: 2, expired: true] [val: 3,
expired: false] [val: 4, expired: false] [val: 5, expired: true]
after: [val: 1, expired: false] [val: 3, expired: false] [val: 4,
expired: false]

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 43


Know your sorts and sorta-sorts
Scott Meyers’ “Effective STL” Item 31

• Sorting algorithms:
– sort1
– stable_sort1
– partial_sort, partial_sort_copy1
• Sorta-sorts:
– nth_element1
– partition, partition_copy2
– stable_partition2
1 Requires random access iterators
2 Requires bidirectional iterators

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 44


Know your sorts
Scott Meyers’ “Effective STL” Item 31

• sort • partial_sort
– Most general-purpose sort – Sort a subset of a sequence,
– Order of equivalent items drawing from a subset that is
implementation-defined equal to or larger than the sorted
– In some cases, may be more sequence
efficient than stable_sort – There is no stable version of
since equivalent items can be partial_sort
rearranged at sort’s discretion • partial_sort_copy
– Sorts in place
– Like partial_sort, but…
• stable_sort – Sorts specified subset of an
– Order of equivalent items input sequence, emitting to an
preserved output sequence
– Sorts in place

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 45


sort and stable_sort
sort objects by last name, first, middle
• Scenario: assume an object with strings
containing fist name, middle name, and last
name, among other things
struct Person {
string first;
string middle;
string last;
… other Person stuff…
};

• We want to sort said objects by all three fields,


with precedence last > first > middle
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 46
sort and stable_sort
sort objects by last name, first, middle
vector<Person> v{{
{ "Joe", "P", "Smith" },
{ "Jane", "Q", "Jones" },
{ "Frank", "P", "Johnson" },
{ "Sarah", "B", "Smith" },
{ "Joe", "X", "Jones" },
{ "Joe", "A", "Smith" } }};

// Sort by least influential data first


sort(v.begin(), v.end(),
[](const Person& a, const Person& b){ return a.middle < b.middle; });

stable_sort(v.begin(), v.end(),
[](const Person& a, const Person& b){ return a.first < b.first; });

stable_sort(v.begin(), v.end(),
[](const Person& a, const Person& b){ return a.last < b.last; });
// Sort by most influential data last

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 47


sort and stable_sort
sort objects by last name, first, middle
vector<Person> v{{
{ "Joe", "P", "Smith" },
{ "Jane", "Q", "Jones" },
{ "Frank", "P", "Johnson" },
{ "Sarah", "B", "Smith" },
{ "Joe", "X", "Jones" },
{ "Joe", "A", "Smith" } }};

// Sort by least influential data first


sort(v.begin(), v.end(),
[](const Person& a, const Person& b){ return a.middle < b.middle; });

stable_sort(v.begin(), v.end(),
[](const Person& a, const Person& b){ return a.first < b.first; });

stable_sort(v.begin(), v.end(),
[](const Person& a, const Person& b){ return a.last < b.last; });
// Sort by most influential data last

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 48


sort and stable_sort
sort objects by last name, first, middle
vector<Person> v{{
{ "Joe", "P", "Smith" },
{ "Jane", "Q", "Jones" },
{ "Frank", "P", "Johnson" },
{ "Sarah", "B", "Smith" },
{ "Joe", "X", "Jones" },
{ "Joe", "A", "Smith" } }};

// Sort by least influential data first


sort(v.begin(), v.end(),
[](const Person& a, const Person& b){ return a.middle < b.middle; });

stable_sort(v.begin(), v.end(),
[](const Person& a, const Person& b){ return a.first < b.first; });

stable_sort(v.begin(), v.end(),
[](const Person& a, const Person& b){ return a.last < b.last; });
// Sort by most influential data last

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 49


sort and stable_sort
visual: sort objects by last name, first, middle

sort, middle initial stable_sort, first name stable_sort, last name

Joe P Smith Joe A Smith Frank P Johnson Frank P Johnson


Jane Q Jones Sarah B Smith Jane Q Jones Jane Q Jones
Frank P Johnson Joe P Smith Joe A Smith Joe X Jones
Sarah B Smith Frank P Johnson Joe P Smith Joe A Smith
Joe X Jones Jane Q Jones Joe X Jones Joe P Smith
Joe A Smith Joe X Jones Sarah B Smith Sarah B Smith

Undefined order for Order preserved from Order preserved from


items with equality prior sort for items prior sort for items
with equality with equality

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 50


partial_sort
• Takes an input sequence of sort candidates
• Sorts the top n elements into a potentially smaller
output sequence
• Order of items from input sequence that are
unsorted in output sequence are in implementation
defined order
• partial_sort is an in-place operation
• partial_sort_copy copies sorted output to a
separate sequence
• partial_sort is obviously more efficient than a
full sort
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 51
partial_sort example
vector<int> v1{ 42, 17, 89, 22,
34, 78, 63, 12,
57, 99 };

partial_sort(v1.begin(),
v1.begin() + 5,
v1.begin() + 8,
greater<int>());
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 52
partial_sort example
vector<int> v1{ 42, 17, 89, 22,
34, 78, 63, 12,
57, 99 };

partial_sort(v1.begin(),
v1.begin() + 5,
v1.begin() + 8,
greater<int>());
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 53
partial_sort example
vector<int> v1{ 42, 17, 89, 22,
34, 78, 63, 12,
57, 99 };

partial_sort(v1.begin(),
v1.begin() + 5,
v1.begin() + 8,
greater<int>());
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 54
partial_sort example
visual
first first
42 89
17 78
89 63 sort output range
22 42
sort input range
34 34
middle
78 17
63 22
12 12
last
57 57
99 99

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 55


Know your sorta-sorts
Scott Meyers’ “Effective STL” Item 31

• partition – Operates in place


– Reorder sequence so all • partition_copy
items before partition point – Like partition, but…
are less, and all items after
– Order of equivalent items is
are not less implementation-defined
– Order of items in lower and
– Copies items from input
upper subsets is sequence to one of two
implementation defined
output sequences depending
– Order of equivalent items is on whether supplied function
implementation-defined object returns false or true for
– Operates in place each item
• stable_partition – There is no
– Like partition, but… stable_partition_copy
– Order of equivalent items is
preserved

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 56


Know your sorta-sorts, cont.
Scott Meyers’ “Effective STL” Item 31

• nth_element
– Reorders sequence such that all items before “nth”
are less, and all items after “nth” are not less
– Order of items in lower and upper subsets is
implementation defined
– Order of equivalent items is implementation-
defined
– “nth” element is exactly the value that would exist
in a fully sorted sequence (but without fully sorting)
– Operates in place

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 57


Know your sorta-sorts, cont.
Comparison between partition and nth_element

partition nth_element
• partitions a sequence, based • partitions a sequence, based
on condition on position
• partition point is not • nth element is element that
guaranteed to be value that would exist in that position in
would be at that position in
fully sorted sequence
fully sorted sequence
• input: • input:
– sequence begin, end – sequence begin, end
– comparison function – iterator to “nth” position
• output: – optional comparison function
– reordered sequence • output:
– iterator to partition point – reordered sequence, partitioned
around nth element

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 58


partition example
partition elements around 50
vector<int> v{ 12, 89, 31, 18,
7, 72, 69, 50,
49, 50, 51, 49 };

vector<int>::iterator part_it =
partition(v.begin(),
v.end(),
[](const int i) {
return i < 50;
});

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 59


partition example
partition elements around 50
vector<int> v{ 12, 89, 31, 18,
7, 72, 69, 50,
49, 50, 51, 49 };

vector<int>::iterator part_it =
partition(v.begin(),
v.end(),
[](const int i) {
return i < 50;
});

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 60


partition example
visual: partition elements around 50
12 12
89 49
31 31
18 18
7 7
72 49 partition
point
69 69
50 50
49 72
50 50
51 51
49 89

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 61


partition_copy example
partition elements around 50
vector<int> v{ 12, 89, 31, 18,
7, 72, 69, 50,
49, 50, 51, 49 };

partition_copy(v.begin(),
v.end(),
back_inserter(smaller),
back_inserter(larger),
[](const int i) {
return i < 50;
});
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 62
partition_copy example
visual: partition elements around 50
input sequence
12
12
31
89
18 output sequence
31 < 50
7 (condition true)
18
49
7
49
72
69
89
50
72
49 output sequence
69
50 not < 50
50 (condition false)
51
50
49
51

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 63


Mixing up partitions!
partition_copy, partition, and stable_partition example

• Extend our prior Person struct to be an Employee


struct
• Partition Management and Individuals into two
separate containers
• Partition Management between Executives and
Managers
• Partition Architects before other Individuals
• Stable partition the Senior and Junior employees
among already partitioned individuals, leaving
already partitioned elements in same relative
position

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 64


Mixing up partitions!
some data…
struct Employee: public Person {
enum class EmployeeType {
Executive, Manager, Architect, Senior, Junior,
Management = Manager,
Individual = Architect
};
EmployeeType type;

… additional members and methods…


};

vector<Employee> v{
{ "Joe", "P", "Smith", Employee::EmployeeType::Manager },
{ "Jane", "Q", "Jones", Employee::EmployeeType::Junior },
{ "Frank", "P", "Johnson", Employee::EmployeeType::Architect },
{ "Sarah", "B", "Smith", Employee::EmployeeType::Executive },
{ "Joe", "X", "Jones", Employee::EmployeeType::Senior },
{ "Joe", "A", "Smith", Employee::EmployeeType::Junior },
{ "Chris", "M", "Williams", Employee::EmployeeType::Manager }
};

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 65


Mixing up partitions!
separate employees into management and individuals
vector<Employee> management, individuals;
partition_copy(v.begin(), v.end(),
back_inserter(management), back_inserter(individuals),
[](const Employee& e) {
return e.type <= Employee::EmployeeType::Manager;
});

executives get the company jet; managers get the company car
vector<Employee>::iterator car_it =
partition(management.begin(), management.end(),
[](const Employee& e) {
return e.type == Employee::EmployeeType::Executive;
});
vector<Employee>::iterator jet_it = management.begin();

cout << "Management partitioned:\n";


for (auto it = management.begin(); it != management.end(); ++it) {
cout << (it < car_it ? "\tjet" : "\tcar") << *it;
}
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 66
Mixing up partitions!
architects get the company segway; everyone else gets the bike
vector<Employee>::iterator bike_it =
partition(individuals.begin(), individuals.end(),
[](const Employee& e) {
return e.type == Employee::EmployeeType::Architect;
});
vector<Employee>::iterator segway_it = individuals.begin();
cout << "Architects partitioned:\n";
for (auto it = individuals.begin(); it != individuals.end(); ++it) {
cout << (it < bike_it ? "\tsegway" : "\tbike") << *it;
}

partition the non-architects from higher to lower seniority


vector<Employee>::iterator old_bike_it =
stable_partition(individuals.begin(), individuals.end(),
[](const Employee& e) {
return e.type <= Employee::EmployeeType::Senior;
});
cout << "Individuals partitioned:\n";
for (auto it = individuals.begin(); it != individuals.end(); ++it) {
cout << (it < bike_it ? "\tsegway" :
(it < old_bike_it ? "\tnewbike" : "\toldbike")) << *it;
}
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 67
Mixing up partitions!
example output
Management partitioned:
jet Sarah B Smith: Executive
car Joe P Smith: Manager
car Chris M Williams: Manager
Architects partitioned (junior/senior unpartitioned):
segway Frank P Johnson: Architect
bike Jane Q Jones: Junior
bike Joe X Jones: Senior
bike Joe A Smith: Junior
Individuals fully partitioned:
segway Frank P Johnson: Architect
newbike Joe X Jones: Senior
oldbike Jane Q Jones: Junior
oldbike Joe A Smith: Junior
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 68
nth_element (not a super-hero, but still pretty super)
find median value in sequence
vector<int> v{ 12, 2, 89, 78, 18, 7, 72,
69, 81, 50, 49, 50, 51, 49 };

const size_t nth = v.size() / 2;


nth_element(v.begin(), v.begin() + nth, v.end());

output:
49 2 12 49 18 7 50 >50< 51 78 72 69 81 89

find percentile value in sequence


vector<int> v{ 12, 2, 89, 78, 18, 7, 72,
69, 81, 50, 49, 50, 51, 49 };

const size_t percentile = 75;


const size_t nth = v.size() * percentile / 100;
nth_element(v.begin(), v.begin() + nth, v.end());

output:
49 2 12 49 18 7 50 50 51 69 >72< 78 81 89

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 69


partial_sort vs. nth_element + sort

• Scenario: find top (say 20) web pages by


number of hits, among a much larger set
• We have a large sequence where we are only
concerned with the top 20 elements
• We want the top 20 elements of this sequence
in order; we don’t care about the rest
• Requirement: top 20 must be partitioned to
front of sequence, before the don’t-cares
• Requirement: top 20 must be sorted
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 70
partial_sort vs. nth_element + sort

partial_sort(vec.begin(),
vec.begin() + 20,
vec.end(),
greater<int64_t>());

nth_element(vec.begin(),
vec.begin() + 20,
vec.end(),
greater<int64_t>());
sort(vec.begin(), vec.begin() + 20,
greater<int64_t>());

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 71


partial_sort vs. nth_element + sort
• Are they equivalent?

vector<int64_t> v1 = init_vec();
vector<int64_t> v2 = v1; // make a copy

partial_sort(v1.begin(), v1.begin() + 20, v1.end(), greater<int64_t>());

nth_element(v2.begin(), v2.begin() + 20, v2.end(), greater<int64_t>());


sort(v2.begin(), v2.begin() + 20, greater<int64_t>());

cout << "sorted portions of vectors are equal: " << boolalpha
<< equal(v1.begin(), v1.begin() + 20, v2.begin()) << endl;
cout << "unsorted portions of vectors are equal: " << boolalpha
<< equal(v1.begin() + 20, v1.end(), v2.begin() + 20) << endl;

output:
sorted portions of vectors are equal: true
unsorted portions of vectors are equal: false

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 72


rotate
• Moves elements specified in a source range to
destination position, while moving displaced items to
source position
• Simple way to move one or more elements from one
position in a container to another without using erase and
insert
• Technically, this is a left rotate
• rotate moves element in the sequence in-place
• rotate_copy does the same, except that it copies the
elements to a separate sequence
• Requires:
– [first, middle) and [middle, last) are valid ranges
– i.e. first <= middle <= last
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 73
rotate
A naïve implementation – move one item in sequence

vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

vector<int>::iterator it = v.begin() + 2;
int i = *it;
v.erase(it);

vector<int>::iterator it2 = v.begin() + 6 - 1;


v.insert(it2, i);

Output:
before: 0 1 2 3 4 5 6 7 8 9
After: 0 1 3 4 5 2 6 7 8 9

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 74


rotate
A naïve implementation – move one item in sequence

vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

vector<int>::iterator it = v.begin() + 2;
int i = *it;
v.erase(it);

vector<int>::iterator it2 = v.begin() + 6 - 1;


v.insert(it2, i);

Output:
before: 0 1 2 3 4 5 6 7 8 9
After: 0 1 3 4 5 2 6 7 8 9

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 75


rotate
A better implementation – move one item in sequence

vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

vector<int>::iterator it = v.begin() + 2;
vector<int>::iterator it2 = v.begin() + 6;
rotate(it, it + 1, it2);

Output:
before: 0 1 2 3 4 5 6 7 8 9
After: 0 1 3 4 5 2 6 7 8 9

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 76


rotate
Rotate a range of items

vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

vector<int>::iterator it = v.begin() + 2;
vector<int>::iterator it2 = v.begin() + 7;
rotate(it, it + 3, it2);

Output:
before: 0 1 2 3 4 5 6 7 8 9
after: 0 1 5 6 2 3 4 7 8 9

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 77


rotate
GCC’s definition

• Rotates the elements of the range


[first, last) by (middle - first)
positions so that the element at middle is
moved to first, the element at middle
+ 1 is moved to first + 1 and so on
for each element in the range.
• This effectively swaps the ranges [first,
middle) and [middle, last).
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 78
slide (move range of elements to new position)
Sean Parent, “C++ Seasoning”
• What if you wanted to implement an
algorithm that would move a range
to a point in either direction without
f worrying about iterator ordering?
• For example, move a range of
l
selected GUI items to a new position
r in a list.
• When using rotate, it is important
p
to get the order of iterators correct:
first <= middle <= last.
• Bonus: return a pair indicating
destination range of relocated
elements.
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 79
slide (move range of elements to new position)
Sean Parent, “C++ Seasoning”
• What if you wanted to implement an
algorithm that would move a range
to a point in either direction without
f worrying about iterator ordering?
• For example, move a range of
l
selected GUI items to a new position
r in a list.
• When using rotate, it is important
p
to get the order of iterators correct:
first <= middle <= last.
• Bonus: return a pair indicating
destination range of relocated
elements.
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 80
slide (move range of elements to new position)
Sean Parent, “C++ Seasoning”
• What if you wanted to implement an
algorithm that would move a range
to a point in either direction without
pf worrying about iterator ordering?
• For example, move a range of
l r
selected GUI items to a new position
f r in a list.
• When using rotate, it is important
pl
to get the order of iterators correct:
first <= middle <= last.
• Bonus: return a pair indicating
destination range of relocated
elements.
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 81
slide (move range of elements to new position)
Sean Parent, “C++ Seasoning”
• What if you wanted to implement an
algorithm that would move a range
to a point in either direction without
pf worrying about iterator ordering?
• For example, move a range of
l r
selected GUI items to a new position
f r in a list.
• When using rotate, it is important
pl
to get the order of iterators correct:
first <= middle <= last.
• Bonus: return a pair indicating
destination range of relocated
elements.
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 82
slide (move range of elements to new position)
Sean Parent, “C++ Seasoning”

f p

l r
r f

p l

template <typename I> // I models RandomAccessIterator


auto slide(I f, I l, I p) -> pair<I, I> {
if (p < f)
return { p, rotate(p, f, l) };
if (l < p)
return { rotate(f, l, p), p };
return { f, l };
}

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 83


gather (gather multiple elements around a point)
Sean Parent, “C++ Seasoning”
• What if you wanted to implement an
algorithm that would allow a scattered
selection of elements to be gathered to a
specific location?
• For example, move a range of scattered
multi-selected GUI items to a new
p position in a list, gathered together.
f
• How can you gather diverse elements to
a single location without loops and
special-casing code?
• Bonus: return a pair indicating destination
range of relocated elements.

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 84


gather (gather multiple elements around a point)
Sean Parent, “C++ Seasoning”
• What if you wanted to implement an
algorithm that would allow a scattered
selection of elements to be gathered to a
specific location?
• For example, move a range of scattered
f
multi-selected GUI items to a new
p position in a list, gathered together.
f
• How can you gather diverse elements to
l a single location without loops and
special-casing code?
• Bonus: return a pair indicating destination
range of relocated elements.

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 85


gather (gather multiple elements around a point)
Sean Parent, “C++ Seasoning”

• Break the problem space into


two pieces:
– The sequence before the
destination position
p
f
– The sequence after the
destination position
• What algorithm can gather the
select items while maintaining
their relative position?
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 86
gather (gather multiple elements around a point)
Sean Parent, “C++ Seasoning”

• Break the problem space


into two pieces:
f
– The sequence before the
destination position
p
f
– The sequence after the
l
destination position

• That looks a lot like


partitioning…
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 87
gather (gather multiple elements around a point)
Sean Parent, “C++ Seasoning”
template <typename I, // models BidirectionalIterator
typename S> // models UnaryPredicate
auto gather(I f, I l, I p, S s) -> pair<I, I>
{
return { stable_partition(f, p, not1(s)),
stable_partition(p, l, s) };
} f

rf
rf

rl
rl

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 88


set_difference
process configuration updates

• Scenario: you store some configuration


information in an ordered container
• You receive updated configuration on a
regular basis
• You want to quickly determine what has
changed: i.e. what new items have been
added, and what items have been removed

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 89


set_difference
process configuration updates
vector<string> new_items, removed_items;

set_difference(current.begin(), current.end(),
update.begin(), update.end(),
back_inserter(removed_items));
remove_config(removed_items);

set_difference(update.begin(), update.end(),
current.begin(), current.end(),
back_inserter(new_items));
add_config(new_items);

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 90


set_difference
process configuration updates test example
set<string> current { "one", "two", "three", "four", "five" };
set<string> update { "one", "three", "four", "six", "seven" };

vector<string> new_items, removed_items;

set_difference(current.begin(), current.end(),
update.begin(), update.end(),
back_inserter(removed_items));
remove_config(removed_items);

set_difference(update.begin(), update.end(),
current.begin(), current.end(),
back_inserter(new_items));
add_config(new_items);

output:
Removed: five two
Added: seven six

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 91


Coming soon to a compiler near you!
Parallel algorithms

• Currently experimental, proposed for a future


release.
• In the std::experimental::parallel
namespace.
• Have the same interfaces as standard
algorithms.
• Controlled by use of parallelism
execution_policy.
• See the Parallelism Technical Specification for
more info.
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 92
A quick review…
• Be familiar with all the varied algorithms
provided for free with your compiler
• Write some code that exercises each of
them so you are familiar with their usage
and individual personalities
• Write your own adaptations of existing
algorithms
• Implement your own algorithms
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 93
STL algorithms
non-modifying sequence operations
• all_of • adjacent_find
• any_of • count
• none_of – count_if
• for_each • mismatch
• find • equal
– find_if • is_permutation
– find_if_not • search
• find_end – search_n
• find_first_of
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 94
STL algorithms
mutating sequence operations
• copy • remove
– copy_n – remove_if
– copy_if – remove_copy
– copy_backward – remove_copy_if
• move • unique
– move_backward – unique_copy
• swap_ranges • reverse
– iter_swap – reverse_copy
• transform • rotate
• replace – rotate_copy
– replace_if • shuffle
– replace_copy – random_shuffle
– replace_copy_if • partition
• fill – is_partitioned
– fill_n – stable_partition
• generate – partition_copy
– generate_n – partition_point

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 95


STL algorithms
sorting and related operations
• sorting • heap operations
– sort – push_heap
– stable_sort – pop_heap
– partial_sort – make_heap
– partial_sort_copy – sort_heap
• nth_element • minimum and maximum
• binary search – min
– lower_bound – max
– upper_bound – minmax
– equal_range – min_element
– binary_search – max_element
• merge – minmax_element
– merge • lexicographical comparisons
– inplace_merge – lexicographical_compare
• set operations on sorted • permutation generators
structures – next_permutation
– includes – prev_permutation
– set_union
– set_intersection
– set_difference
– set_symmetric_difference

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 96


STL algorithms
general numeric operations

• accumulate
• inner_product
• partial_sum
• adjacent_difference
• iota

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 97


Shout out to my “sponsor”
• F5 Networks is a highly technical company
with a belief in well engineered software
• F5 Networks has graciously sent me here,
and they tolerate encourage me working on
this stuff in addition to my “real” work
• If you’re looking for something cool and
challenging to do with C++, check out F5!
• https://f5.com/about-us/careers
STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 98
Shameless advertising…
• I’m working on a book on this very topic!
• It isn’t done yet…
• If you have some creative or clever uses of
STL algorithms you’d like me consider, please
drop me a line with some example code!
[email protected]
• Visit my blog for more adventures:
http://codeache.net

STL Algorithms in Action Michael VanLoon - http://codeache.net - CPPcon 2015 99

You might also like