Standard Library Range UtilitiesStandard Library Range UtilitiesRange Utilities
New to C++'s standard library algorithms? ⇒ Short Introduction
returns the size of an iterator range
distance(@range_begin, @element_in_range)
→ index_of_element_in_range
#include <vector>
#include <iterator> // std::distance
std::vector<int> v {0,1,2,3,4,5,6,7,8};
// size of subrange (as shown in image)
auto n = distance(begin(v)+2, begin(v)+7); // int n = 5
// size of entire container
auto m = distance(begin(v), end(v)); // int m = 9
std::vector<int> w {4,5,1,9,8};
// get index of smallest element in w:
auto argmin = distance( begin(w), min_element(begin(w),end(w)) );
// int argmin = 2
Avoid using distance
with iterators into non-random access
containers like std::list
, because the runtime will be
proportional to the size of the input range!
- convenient if you already have a function(object) to be applied to each element
- works for all standard sequence and associative containers
- container agnostic ⇒ easy to change container type
- no signed/unsigned index type hassle
- self-documenting name
- out-of-bounds access bugs possible with iterator ranges
#include <ranges> // std::ranges::for_each
namespace ranges = std::ranges; // alias
ranges::for_each(v, [](auto x){ cout << x; });
ranges::for_each(v, [](auto const& x){ cout << x; });
ranges::for_each(v, [](auto& x){ cin >> x; });
#include <algorithm> // std::for_each
// read-only, type cheap to copy or copy needed:
for_each(begin(v), end(v), [](Type x){ cout << x; });
for_each(begin(v), end(v), [](auto x){ cout << x; });
for_each(begin(v)+2, begin(v)+5, [](auto x){ cout << x; });
for_each(begin(v)+5, end(v), [](auto x){ cout << x; });
// read-only, type expensive to copy:
for_each(begin(v), end(v), [](Type const& x){ cout << x; });
for_each(begin(v), end(v), [](auto const& x){ cout << x; });
// modify values:
for_each(begin(v), end(v), [](Type& x){ cin >> x; });
for_each(begin(v), end(v), [](auto& x){ cin >> x; });
#include <algorithm> // std::for_each_n
auto const n = container.size() / 2;
for_each_n(begin(v), n, [](auto x){ cout << x; });
for_each_n(begin(v), n, [](auto const& x){ cout << x; });
for_each_n(begin(v), n, [](auto& x){ cin >> x; });
#include <iterator>
Functions std::prev
and std::next
provide a universal way of incrementing/decrementing iterators
even if the iterator type does not support random access
(e.g., it += 5
).
However, be aware that advancing non-random access iterators
(e.g., those from std::list
) by N
steps might be
costly, i.e., involve on the order of N
memory operations.
std::vector<int> v {1,2,3,4,5,6};
auto i = next(v.begin());
auto j = next(i, 3);
std::vector<int> v {1,2,3,4,5,6};
auto i = prev(v.end());
i = prev(i);
auto j = prev(i, 3);
- 1
- 2
- 3
- 4
- 5
- 6
-
-
-
-
-
-
- i
-
-
-
-
- i
-
-
- j
-
- i
-