Standard Library Element-Wise Range ModificationsElement-Modifying AlgorithmsChange
New to C++'s standard library algorithms? ⇒ Short Introduction
Filling / Overwriting Ranges Filling Ranges Fill
std::vector<int> v {1,0,9,0,9,1,0,1};
fill(begin(v)+2, begin(v)+7, 2);
for(int x : v) { cout << x << ' '; } // 1 0 2 2 2 2 2 1
std::vector<int> v {1,0,9,0,9,1,0,1};
fill_n(begin(v)+2, 5, 2);
for(int x : v) { cout << x << ' '; } // 1 0 2 2 2 2 2 1
std::vector<int> v {9,0,9,1,0};
std::ranges::fill(v, 2);
for(int x : v) { cout << x << ' '; } // 2 2 2 2 2
Example: C++14-Lambda As Generator
auto gen = [i=0]() mutable { i += 2; return i; };
// init-^^^ ^^^^^^^⇒ member 'i' changeable!
cout << gen(); // 2
cout << gen(); // 4
cout << gen(); // 6
Example: Generator Function Class
class int_range_generator {
int val_ = 0;
int step_ = 1;
public:
int_range_generator() = default;
explicit constexpr
int_range_generator(int start, int step=1) noexcept:
val_{start}, step_{step} {}
constexpr int operator () () noexcept {
int const old = val_;
val_ += step_;
return old;
}
};
auto gen = int_range_generator{2,2};
cout << gen(); // 2
cout << gen(); // 4
cout << gen(); // 6
auto gen = [i=0]() mutable { i += 2; return i; };
std::vector<int> v;
v.resize(7,0);
generate(begin(v)+1, begin(v)+5, gen);
for(int x : v) { cout << x << ' '; } // 0 2 4 6 8 0 0
auto gen = [i=0]() mutable { i += 2; return i; };
std::vector<int> v;
v.resize(7,0);
generate_n(begin(v)+1, 4, gen);
for(int x : v) { cout << x << ' '; } // 0 2 4 6 8 0 0
auto gen = [i=0]() mutable { i += 2; return i; };
std::vector<int> v;
v.resize(4,0);
std::ranges::generate(v, gen);
for(int x : v) { cout << x << ' '; } // 2 4 6 8
This algorithm is also known as map
in other programming languages.
The output target must be able to recieve as many elements as there are in the input range.
The function (object) f
must not have side effects (e.g. have state)
because there is no guaranteed order in which it is applied to the input elements.
// f: 'x' → "<x>"
auto f = [](char c) { return std::string("<") + c + ">"; };
std::string in = "vwxyza";
std::vector<std::string> out;
// make sure 'out' can fit result
out.resize(4);
transform(begin(in)+1, begin(in)+5, begin(out), f);
for(auto const& x : out) { cout << x << ' '; } // <w> <x> <y> <z>
// f: 'y',3 → "yyy"
auto f = [](char c, int i) { return std::string(c,i); };
std::string in1 = "wxy";
std::vector<int> in2 = {1,2,3};
std::vector<std::string> out;
// make sure 'out' can fit result
out.resize(3);
transform(begin(in1), end(in1), begin(in2), begin(out), f);
for(auto const& x : out) { cout << x << ' '; } // w xx yyy
// f: 'x' → "<x>"
auto f = [](char c) { return std::string("<") + c + ">"; };
std::string in = "wxyz";
std::vector<std::string> out;
// make sure 'out' can fit result
out.resize(4);
std::ranges::transform(in, begin(out), f);
for(auto const& x : out) { cout << x << ' '; } // <w> <x> <y> <z>
// f: 'y',3 → "yyy"
auto f = [](char c, int i) { return std::string(c,i); };
std::string in1 = "wxyz";
std::vector<int> in2 = {1,2,3};
std::vector<std::string> out;
// make sure 'out' can fit result
out.resize(3);
std::ranges::transform(in1, in2, begin(out), f);
for(auto const& x : out) { cout << x << ' '; } // w xx yyy
replace
/ replace_if
replace
_if
replace
std::vector<int> v {1,2,3,2,4,2,2,6};
replace(begin(v)+2, begin(v)+7, 2, 0)
for(int x : v) { cout << x << ' '; } // 1 2 3 0 4 0 0 6
std::vector<int> v {3,2,4,2,2};
std::ranges::replace(v, 2, 0)
for(int x : v) { cout << x << ' '; } // 3 0 4 0 0
auto const is_even = [](int x) { return !(x & 1); };
std::vector<int> v {1,2,3,2,5,2,2,6,7};
replace_if(begin(v)+2, begin(v)+7, is_even, 0)
for(int x : v) { cout << x << ' '; } // 1 2 3 0 4 0 0 6 7
auto const is_even = [](int x) { return !(x & 1); };
std::vector<int> v {3,2,5,4,6};
std::ranges::replace_if(v, is_even, 0)
for(int x : v) { cout << x << ' '; } // 3 0 5 0 0
replace_copy
/ replace_copy_if
replace_copy
/_copy_if
replace_copy
The output target must be able to recieve as many elements as there are in the input range.
std::vector<int> in {1,2,3,2,4,2,2,6,7};
std::vector<int> out;
out.resize(5);
replace_copy(begin(in)+2, begin(in)+7, begin(out), 2, 0)
for(int x : out) { cout << x << ' '; } // 3 0 4 0 0
std::vector<int> in {3,2,4,2,2};
std::vector<int> out;
out.resize(5);
std::ranges::replace_copy(in, out, 2, 0)
for(int x : out) { cout << x << ' '; } // 3 0 4 0 0
auto const is_even = [](int x) { return !(x & 1); };
std::vector<int> in {2,3,2,5,4,6,6};
std::vector<int> out;
out.resize(5);
replace_copy_if(begin(in)+2, begin(in)+7, begin(out), is_even, 0)
for(int x : out) { cout << x << ' '; } // 3 0 5 0 0
auto const is_even = [](int x) { return !(x & 1); };
std::vector<int> in {3,2,5,4,6};
std::vector<int> out;
out.resize(5);
std::ranges::replace_copy_if(in, out, is_even, 0)
for(int x : out) { cout << x << ' '; } // 3 0 5 0 0
Related …
- generate & generate_n by Conor Hoekstra
- Standard Algorithms Overview
- Standard Algorithms Introduction
- Standard Sequence Containers (
vector
,deque
,list
, …) - Standard Associative Containers (
map
,set
, …) - Standard Sequence Views
- cppreference: Algorithms Library
- cppreference: Containers Library
- A Tour of C++: Containers and Algorithms
- Algorithms Overview Sheet