Getting started
If you experience problems loading range-v3 in Wandbox, use Godbolt:
- Go to: https://godbolt.org/
- Choose x86-64 GCC trunk
- In the Library menu choose range-v3
- In the Output menu choose Execute the code
- Insert the following code and make sure it compiles:
#include <iostream> #include <range/v3/all.hpp> int main(){ // your code goes here }Practical examples can be found here.
The original Ranges book - all you will ever need to know.
Range-v3 vs C++23 Ranges
The following names have been adopted by C++23 Ranges.
Range-v3 C++23 views::group_by views::chunk_by views::sliding views::slide, views::adjacent views::zip_with views::zip_transform
Missing from some of the C++23 compilers
The algorithms below are important for practical examples but still missing in some of the C++23 compilers (see compiler-specific info).
Range-v3 C++23 ranges::to Clang, MSVC ranges::fold_left GCC, MSVC
Proposed only in C++26
The following mission critical views from range-v3 will only be implemented in C++26.
Range-v3 C++26 views::cycle Tier 1 views::concat Tier 1 views::partial_sum Tier 1 as views::scan views::exclusive_scan not proposed views::generate Tier 1
fold_left / accumulate
Ex.1 Sum up elements of a range, starting from the value 0.0.
// (a -> b -> a) -> a -> [b] -> a // foldl (+) 0.0 [1.5,2.7,3.8,4.2] auto const v = std::vector<double> {1.5,2.7,3.8,4.2}; auto val1 = ranges::fold_left(v, 0.0, std::plus{}); // 12.2 auto val2 = ranges::accumulate(v, 0.0); // 12.2Ex.2 Fold elements of a range via multiplication, starting from the value 1.
// (a -> b -> a) -> a -> [b] -> a // foldl (*) 1 [1,2,3,4] auto const v = std::vector<int> {1,2,3,4}; auto val1 = ranges::fold_left(v, 1, [](int a, int b){return a * b;}); // 24 auto val2 = ranges::accumulate(v, 1, [](int a, int b){return a * b;}); // 24
copy
Ex.1 Copy a source range into a destination range.
std::vector<int> v {6,4,1,8,3}; std::vector<int> v2; ranges::copy(v, ranges::back_inserter(v2)); std::cout << ranges::views::all(v2); // [6,4,1,8,3]Ex.2 Copy a source range into a destination range.
auto v = std::vector<int> {5,6,7,8,7}; auto v2 = ranges::copy(v); std::cout << ranges::views::all(v2); // [5,6,7,8,7]
count
Ex.1 Count the number of occurrences of the number 7.
auto const v = std::vector<int> {1,2,7,4,1,7}; auto val = ranges::count(v,7); // 2
distance
Ex.1 Return the distance between the beginning and the end of the range.
auto const v1 = std::vector<char> {'a','b','c'}; auto const v2 = std::vector<char> {'c','d','e'}; auto v3 = ranges::views::set_union(v1,v2); auto sz = ranges::distance(v3); // 5
equal
Ex.1 Determine equality of two vectors.
// [1, 2, 3] == [3, 2, 1] auto const v1 = std::vector<int> {1,2,3}; auto const v2 = std::vector<int> {3,2,1}; auto val = ranges::equal(v1,v2); // falseEx.2 Determine equality of two strings.
auto const s1 = std::string{"world"}; auto const s2 = std::string{"WORLD"}; auto val = ranges::equal(s1,s2); // false
find
Ex.1 Find the first occurence of a specific value.
auto v = std::vector<int> {5,6,7,8,7}; auto it = ranges::find(v,7); assert(it == v.begin() + 2);
for_each
Ex.1 Print all the elements of a range.
auto const v = std::vector<int> {1,2,3,4}; ranges::for_each(v, [](int i){ std::cout << i << " "; });
front
Ex.1 Retrieve the first element of a range.
auto v = std::vector<int> {5,6,7,8}; auto first = ranges::front(v); // 5
inner_product
Ex.1 Calculate the dot product of two vectors.
auto const v1 = std::vector<int> {1,3,-5}; auto const v2 = std::vector<int> {4,-2,-1}; auto val = ranges::inner_product(v1,v2,0); // 1*4 + 3*(-2) + (-5)*(-1) = 3
partition_copy
Ex.1 Partition a vector into a vector of even and a vector of odd numbers.
std::vector<int> v {6,4,1,8,3}; std::vector<int> even; std::vector<int> odd; ranges::partition_copy(v, ranges::back_inserter(even), ranges::back_inserter(odd), [] (int i) {return i % 2 == 0;}); std::cout << ranges::views::all(even) // [6,4,8] << ranges::views::all(odd); // [1,3]Note: Currently it's not possible to use std::back_inserter with range-v3, as it's not default constructible, it does not satisfy the Iterator concept as defined by the range-v3 library.
sort
Ex.1 Sort elements of a range in ascending order.
// Ord a => [a] -> [a] // sort [6,7,1,3] auto v = std::vector<int> {6,7,1,3}; ranges::sort(v); // [1,3,6,7]Ex.2 Sort elements of a range in descending order.
// Ord a => [a] -> [a] // sort [6,7,1,3] auto v = std::vector<int> {6,7,1,3}; ranges::sort(v, std::greater{}); // [7,6,3,1]Ex.3 Sort metals by their density.
struct Element { std::string name; double density; void print() const { std::cout << name << ' ' << density << '\n'; } }; int main() { auto v = std::vector<Element> {{"Au", 19.3},{"Cu", 8.96},{"Ag", 10.5}}; ranges::sort(v, std::less{}, &Element::density); ranges::for_each(v, &Element::print); /* Cu 8.96 Ag 10.5 Au 19.3 */ }
views::all
Ex.1 Return a view containing all the elements of the source. Useful for converting STL containers to views.
// [a] -> [a] auto const v = std::vector<int> {1,2,3,4,5}; auto rng = v | ranges::views::all; // [1,2,3,4,5] std::cout << rng;
views::cartesian_product
C++23 Tier 1
Ex.1 Lazily create a cartesian product of two ranges.
auto letters = ranges::views::closed_iota('A','C'); auto numbers = ranges::views::closed_iota(1,2); auto rng = ranges::views::cartesian_product(letters, numbers); for(auto[a,b] : rng) std::cout << a << ' ' << b << '\n';// A 1 // A 2 // B 1 // B 2 // C 1 // C 2
views::chunk
C++23 Tier 1
Ex.1 Lazily divide a range into chunks of uniform size, e.g. 4-element chunks.
auto const v = std::vector<int> {1,2,3,4,5,6,7,8}; auto rng = v | ranges::views::chunk(4); // [[1,2,3,4],[5,6,7,8]]
views::chunk_by
This is the replacement for the deprecated views::group_by.
C++23 Tier 1
Ex.1 Lazily group contiguous elements of a range together based on a binary predicate, e.g. odd and even.
// (a -> a -> Bool) -> [a] -> [[a]] auto v = std::vector<int> {7,4,2,6,9}; ranges::sort(v); auto rng = v | ranges::views::chunk_by([](int x, int y) { return x % 2 == y % 2; }); // [[2,4,6],[7,9]]Ex.2 Lazily group identical letters of a string together. This is useful for frequency count.
auto s = std::string {"radar"}; ranges::sort(s); auto rng = s | ranges::views::chunk_by([](char x, char y) { return x == y; }); // [[a,a],[d],[r,r]]
views::common
views::common is useful for mixing non-common ranges with old STL functions such as std::accumulate.
auto v = std::vector{8,7,3}; auto rng = v | views::take_while([](int x){return x > 5 ;}) | views::common; auto res = std::accumulate(rng.begin(),rng.end(),0); // 15You will not need views::common for ranges::accumulate from Range-v3. You can read more about it here.
views::concat
Ex.1 Lazily concatenate ranges.
// [[a]] -> [a] auto v1 = ranges::views::iota(3,6); auto v2 = ranges::views::iota(7,9); auto v3 = ranges::views::iota(11,14); auto rng = ranges::views::concat(v1,v2,v3); // [3,4,5,7,8,11,12,13]
views::counted
Ex.1 Lazily create a range that starts at the iterator begin + 1 and includes the next 2 elements.
auto v = std::vector<int> {6,7,8,9}; auto rng = ranges::views::counted(ranges::begin(v) + 1,2); // [7,8]
views::cycle
Ex.1 Lazily create a quasi-infinite circular range.
// [a] -> [a] // cycle [1,3,9] auto v = {1,3,9}; auto rng = v | ranges::views::cycle; // [1,3,9,1,3,9,1,3,9...]
views::delimit
Ex.1 Lazily delimit a range at the first occurrence of the value or at the end of the source range, whichever comes first.
auto v = {5,8,9,13,10,9}; auto rng = v | ranges::views::delimit(9); // [5,8]
views::drop
Ex.1 Lazily drop the first two elements from the source range.
// Int -> [a] -> [a] // drop 2 [4,9,3,1,7] auto v = {4,9,3,1,7}; auto rng = v | ranges::views::drop(2); // [3,1,7]
views::drop_while
Ex.1 Lazily remove all elements smaller than 5 from the front of a range.
auto v = {2,3,5,6,7}; auto rng = v | views::drop_while([](int x){return x < 5;}); // [5,6,7]
views::enumerate
C++23 Tier 1
Ex.1 Lazily pair elements of the source range with their index.
auto v = std::vector<std::string> {"apple", "banana", "kiwi"}; for (auto&& [first, second] : v | ranges::views::enumerate) { std::cout << first << ", " << second << '\n'; } // 0, apple // 1, banana // 2, kiwi
views::exclusive_scan
Ex.1 Lazily accumulate elements of the source range starting from 0, excluding the last element.
auto const v = std::vector<int> {1,2,3,4}; auto rng = v | views::exclusive_scan(0); // [0,0+1,0+1+2,0+1+2+3]...[0,1,3,6]Ex.2 Lazily accumulate elements of the source range starting from 10, excluding the last element.
auto const v = std::vector<int> {1,2,3,4}; auto rng = v | views::exclusive_scan(10); // [10,10+1,10+1+2,10+1+2+3]...[10,11,13,16]
views::filter
Ex.1 Keep elements greater than 6.
auto v = {7,4,2,6,9}; auto rng = v | ranges::views::filter([](int x){return x > 6;}); // [7,9]
views::for_each
C++23 Tier 1
Ex.2 Lazily generate i+1 and i-1 for elements of a range and flatten the result (flatmap).
auto v = {1,10,100}; auto rng = ranges::views::for_each(v, [](int i){ return ranges::views::linear_distribute(i-1,i+1,2); }); // [0,2,9,11,99,101]
views::generate
Ex.1 Lazily create a range of positive even numbers going to infinity.
// [2,4..] auto rng = ranges::views::generate( [n = 1] () mutable { return 2*(n++); }); // [2,4,6,8...]Ex.2 Lazily create a range of powers of two going to infinity.
// (a -> a) -> a -> [a] // iterate (2*) 1 auto rng = ranges::views::generate( [n = 1] () mutable { return (n <<= 1) >> 1; }); // [1,2,4,8...]
views::group_by
See views::chunk_by.
views::intersperse
Ex.1 Lazily insert underscore between the letters of a string.
// a -> [a] -> [a] auto const s = std::string {"London"}; auto s2 = s | ranges::views::intersperse('_') | to<std::string>(); // L_o_n_d_o_nEx.2 Lazily insert 0 between the numbers of a range.
// a -> [a] -> [a] auto const v = std::vector<int> {1,2,3,4}; auto rng = v | ranges::views::intersperse(0); // [1,0,2,0,3,0,4]
views::iota
Ex.1 Lazily create a range of integers [4,∞).
// [4..] auto rng = ranges::views::iota(4); // [4,5,6,7...]Ex.2 Lazily create a range of integers [8,9,10].
// [8..10] auto rng = ranges::views::iota(8,11); // [8,9,10]Ex.3 Lazily create a range of letters [A,B,C,D,E].
// ['A'..'E'] auto rng = ranges::views::iota('A','F'); // [A,B,C,D,E]
views::join
Ex.1 Lazily flatten a range of ranges.
// [[a]] -> [a] // concat [[1,3], [11,13,15], [25]] auto const v = std::vector<std::vector<int>>{ {1,3}, {11,13,15}, {25}, }; auto rng = v | ranges::views::join; // [1,3,11,13,15,25]
views::keys
Ex.1 Lazily retrieve keys of std::map.
auto const m = std::map<std::string, int> {{"London", 6}, {"New York", 7}}; auto rng = m | ranges::views::keys; // [London,New York]
views::linear_distribute
Ex.1 Lazily create a range of monotonically increasing values between 1.0 and 2.0 with a step 0.25.
auto rng = ranges::views::linear_distribute(1.0,2.0,5); // [1,1.25,1.5,1.75,2]
views::partial_sum
Ex.1 Lazily accumulate elements of the source range.
// [a] -> [a] // scanl1 (+) [1,2,3,4] auto const v = std::vector<int> {1,2,3,4}; auto rng = v | ranges::views::partial_sum(std::plus{}}); // [1,3,6,10]
views::remove_if
Ex.1 Lazily discard even elements in the source range.
// (a -> Bool) -> [a] -> [a] // filter odd [1,2,3,4,5] auto const v = std::vector<int>{1,2,3,4,5}; auto rng = v | ranges::views::remove_if( [](int x){return x % 2 == 0;}); // [1,3,5]
views::repeat
Ex.1 Lazily create a range with all elements equal to 4.
// a -> [a] // repeat 4 auto rng = ranges::views::repeat(4); // [4,4,4,4,4,4,4,..]
views::reverse
Ex.1 Lazily reverse a range.
// [a] -> [a] // reverse [1,2,3,4] auto const v = std::vector<int> {1,2,3,4}; auto rng = v | ranges::views::reverse; // [4,3,2,1]
views::set_difference
Ex.1 Lazily calculate a difference of two input ranges.
// Eq a => [a] -> [a] -> [a] // [3,4,5,6,7] \\ [4,5] auto v1 = std::vector<int> {3,4,5,6,7}; // sort! auto v2 = std::vector<int> {4,5}; // sort! ranges::sort(v1); // sort! ranges::sort(v2); // sort! auto rng = ranges::views::set_difference(v1,v2); // [3,6,7]
views::set_intersection
Ex.1 Lazily calculate an intersection of two input ranges.
// Eq a => [a] -> [a] -> [a] // intersect [3,4,5,6] [5,6,7,8] auto v1 = std::vector<int> {3,4,5,6}; auto v2 = std::vector<int> {5,6,7,8}; ranges::sort(v1); // sort! ranges::sort(v2); // sort! auto rng = ranges::views::set_intersection(v1,v2); // [5,6]
views::set_union
Ex.1 Lazily calculate a union of two input ranges.
// Eq a => [a] -> [a] -> [a] // union [1,2,3] [4,5,6] auto const v1 = std::vector<int> {1,2,3}; auto const v2 = std::vector<int> {4,5,6}; auto rng = ranges::views::set_union(v1,v2); // [1,2,3,4,5,6]
views::single
Ex.1 Lazily lift a value into a single-element range.
auto const rng = ranges::views::single(3); // [3]Ex.2 Lazily lift a range into a range of ranges.
auto const v2 = ranges::views::single(ranges::views::iota(1,5)); // [[1,2,3,4]]
views::slice
Ex.1 Lazily create a slice that starts at the 2nd position (inclusively) and ends at the 4th position (exclusively) of the source range.
auto const v = std::vector<double> {1.1, 7.3, 14.5, 8.5, 17.6}; auto rng = v | ranges::views::slice(2,4); // [14.5,8.5]
views::sliding
C++23 Tier 1 views::slide, views::adjacent
Ex.1 Lazily create a sliding window of adjacent elements.
auto const v = std::vector<int> {1,2,3,4,5}; auto rng = v | views::sliding(2); // [[1,2],[2,3],[3,4],[4,5]]
views::split
Ex.1 Lazily split a string at the whitespace.
auto const s = std::string{"hello world"}; auto rng = s | ranges::views::split(' ') | ranges::to<std::vector<std::string>>(); // materialization // [hello,world]
views::stride
C++23 Tier 1
Ex.1 Lazily move to every third element of the range.
auto const v = std::vector<int>{0,1,2,3,4,5,6}; auto rng = v | ranges::views::stride(3); // [0,3,6]
views::tail
Ex.1 Lazily create a range without the first element of the source range.
// [a] -> [a] // tail [1,2,3,4] auto const v = std::vector<int> {1,2,3,4}; auto rng = v | ranges::views::tail; // [2,3,4]
views::take
Ex.1 Lazily take the first three elements of a range.
// Int -> [a] -> [a] // take 3 [1,2,3,4,5] auto const v = std::vector<int> {1,2,3,4,5}; auto rng = v | ranges::views::take(3); // [1,2,3]
views::take_while
Ex.1 Lazily take elements until the predicate fails.
// (a -> Bool) -> [a] -> [a] auto const v = std::vectorr<int> {1,2,3,4}; auto rng1 = v | ranges::views::transform([](int x){return x*x;}); // [1,4,9,16] auto rng2 = rng1 | ranges::views::take_while([](int x){return x < 10;}); // [1,4,9]
views::tokenize
Ex.1 Lazily break a string into distinct words.
auto const s = std::string{"Have a nice day!"}; auto const rx = std::regex{"[\\w]+"}; auto rng = s | ranges::views::tokenize(rx); std::cout << rng; // [Have,a,nice,day]
views::transform
Ex.1 Lazily multiply elements of a range by 2.
// (a -> b) -> [a] -> [b] // map (2*) [3,2,1] auto const v = std::vector<int> {3,2,1}; auto rng = v | ranges::views::transform( [](int x){return 2*x;}); // [6,4,2]
views::unique
Ex.1 Lazily discard duplicates of neighbouring elements from a range.
// Eq a => [a] -> [a] auto const v = std::vector<int> {1,2,2,3,1,1,2,2}; auto rng = v | ranges::views::unique; // [1,2,3,1,2]
views::values
Ex.1 Lazily retrieve values from std::map.
auto const m = std::map<std::string, int> {{"London", 6}, {"New York", 7}}; auto rng = m | ranges::views::values; // [6,7]
views::zip
C++23 Tier 1
Ex.1 Lazily match Arabic and Chinese numerals.
auto const v_ar = std::vector<int>{1,10,100,1000,10000}; auto const v_cn = std::vector<std::string>{"一","十","百","千","万"}; auto rng = ranges::views::zip(v_ar, v_cn); for (auto&& [first, second] : rng) { std::cout << first << ", " << second << '\n'; } /* 1, 一 10, 十 100, 百 1000, 千 10000, 万 */
views::zip_with
C++23 Tier 1 views::zip_transform
Ex.1 Lazily add two ranges.
// (a -> b -> c) -> [a] -> [b] -> [c] // zipWith (+) [4,2,7] [3,2,1] auto const v1 = std::vector<int> {4,2,7}; auto const v2 = std::vector<int> {3,2,1}; auto rng = ranges::views::zip_with( [](int a, int b){return a + b;}, v1, v2); // [7,4,8]
Tagged: Range-v3