Quick reference for the range-v3 library, the predecessor of Ranges C++20

This page serves as a quick reference for the range-v3 library to get you started. It is being continuosly updated. To try out the library, add #include <range/v3/all.hpp> in https://wandbox.org/. Haskell equivalents are included where applicable (import Prelude, import Data.List) .


Practical examples

Practical examples for Range-v3 can be found here.

Deprecated

  • view::ints is deprecated, use view::iota or view::indices instead.
  • view::bounded is deprecated, use view::common instead.
  • ranges::to_ is deprecated, use ranges::to without underscore instead.

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 val = ranges::accumulate(v, 0.0); // 12.2
Ex.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 val = ranges::accumulate(v, 1, [](int a, int b){return a * b;}); // 24

copy

Ranges TS

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::view::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::view::all(v2); // [5,6,7,8,7]

count

Ranges TS

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

Ranges TS

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::view::set_union(v1,v2);
    auto sz = ranges::distance(v3); // 5

equal

Ranges TS

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); // false
Ex.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

Ranges TS

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::view::all(even) // [6,4,8]
              << ranges::view::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.

reverse_copy

Ex.1 Copy the source vector into the destination vector in the reverse order.
    std::vector<int> v {6,4,1,8,3};   
    std::vector<int> v2;
    
    ranges::reverse_copy(v, ranges::back_inserter(v2));
    std::cout << ranges::view::all(v2); // [3,8,1,4,6]

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]

view::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::view::all; // [1,2,3,4,5]
    std::cout << rng;

view::cartesian_product

Ex.1 Lazily create a range that represents a cartesian product of two ranges.
    auto letters = ranges::view::closed_iota('A','C');
    auto numbers = ranges::view::closed_iota(1,2);	
    
    auto rng = ranges::view::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

view::chunk

Ex.1 Lazily create range of ranges in the form of chunks, e.g. 4-element chunks.
    auto const v = std::vector<int> {1,2,3,4,5,6,7,8};
    auto rng = v | ranges::view::chunk(4); // [[1,2,3,4],[5,6,7,8]]

view::concat

Ex.1 Lazily concatenate ranges.
    // [[a]] -> [a]
    auto v1 = ranges::view::iota(3,6);
    auto v2 = ranges::view::iota(7,9);
    auto v3 = ranges::view::iota(11,14);
    auto rng = ranges::view::concat(v1,v2,v3); // [3,4,5,7,8,11,12,13]

view::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::view::counted(ranges::begin(v) + 1,2); // [7,8]

view::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::view::cycle; // [1,3,9,1,3,9,1,3,9...]

view::delimit

Ex.1 Lazily create a range that ends 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::view::delimit(9); // [5,8]

view::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::view::drop(2); // [3,1,7]

view::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 | view::drop_while([](int x){return x < 5;}); // [5,6,7]

view::enumerate

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::view::enumerate) {
         std::cout << first << ", " << second << '\n';
    }
    // 0, apple
    // 1, banana
    // 2, kiwi

view::for_each

Ex.2 Lazily generate i+1 and i-1 for elements of a range and flatten the result (flatmap).
Note: Doesn't work for GCC 9.0.0. Works for GCC 8.2.0, CLANG 8.0.0.
    auto v = {1,10,100};
    auto rng = ranges::view::for_each(v, [](int i){
        return ranges::yield_from(ranges::view::linear_distribute(i-1,i+1,2));
    }); // [0,2,9,11,99,101]

view::generate

Ex.1 Lazily create a range of positive even numbers going to infinity.
    //    [2,4..]
    auto rng = ranges::view::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::view::generate(
                     [n = 1] () mutable { return (n <<= 1) >> 1; }); // [1,2,4,8...]

view::group_by

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::view::group_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::view::group_by([](int x, int y) { 
                                             return x == y; }); // [[a,a],[d],[r,r]]

view::intersperse

Ex.1 Lazily insert underscore between the letters of a string.
    // a -> [a] -> [a]
    auto const s = std::string {"London"};
    std::string rng = s | ranges::view::intersperse('_'); // L_o_n_d_o_n
Ex.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::view::intersperse(0); // [1,0,2,0,3,0,4]

view::iota

Ex.1 Lazily create a range of integers [4,∞).
    // [4..]
    auto rng = ranges::view::iota(4); // [4,5,6,7...]
Ex.2 Lazily create a range of integers [8,9,10].
    // [8..10]
    auto rng = ranges::view::iota(8,11); // [8,9,10]
Ex.3 Lazily create a range of letters [A,B,C,D,E].
    // ['A'..'E']
    auto rng = ranges::view::iota('A','F'); // [A,B,C,D,E]

view::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::view::join; // [1,3,11,13,15,25]

view::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::view::keys; // [London,New York]

view::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::view::linear_distribute(1.0,2.0,5); // [1,1.25,1.5,1.75,2]

view::partial_sum

Ex.1 Lazily create a range by cumulatively adding 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::view::partial_sum(std::plus<>()); // [1,3,6,10]

view::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::view::remove_if(
                         [](int x){return x % 2 == 0;}); // [1,3,5]

view::repeat

Ex.1 Lazily create a range with all elements equal to 4.
    // a -> [a]
    // repeat 4
    auto rng = ranges::view::repeat(4); // [4,4,4,4,4,4,4,..]

view::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::view::reverse; // [4,3,2,1]

view::set_difference

Ex.1 Lazily create a range as 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::view::set_difference(v1,v2); // [3,6,7]

view::set_intersection

Ex.1 Lazily create a range as 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::view::set_intersection(v1,v2); // [5,6]

view::set_union

Ex.1 Lazily create a range as 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::view::set_union(v1,v2); // [1,2,3,4,5,6]

view::single

Ex.1 Lazily lift a value into a single-element range.
    auto const rng = ranges::view::single(3); // [3]
Ex.2 Lazily lift a range into a range of ranges.
    auto const v2 = ranges::view::single(ranges::view::iota(1,5)); // [[1,2,3,4]]

view::slice

Ex.1 Lazily create a range 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::view::slice(2,4); // [14.5,8.5]

view::sliding

Ex.1 Lazily create a range of pairs of adjacent elements.
    auto v = std::vector<int> {1,2,3,4,5};
    auto rng = v | view::sliding(2); // [[1,2],[2,3],[3,4],[4,5]]

view::split

Ex.1 Split a string at the whitespace.
    auto s = std::string{"hello world"};
    std::vector<std::string> rng = s | ranges::view::split(' '); // eager evaluation
    std::cout << ranges::view::all(rng); // [hello,world]

view::stride

Ex.1 Lazily move to every third element in the range.
    auto const v = std::vector<int>{0,1,2,3,4,5,6};
    auto rng = v | ranges::view::stride(3); // [0,3,6]

view::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::view::tail; // [2,3,4]

view::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::view::take(3); // [1,2,3]

view::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::view::tokenize(rx);
    std::cout << rng; // [Have,a,nice,day]

view::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::view::transform(
                         [](int x){return 2*x;}); // [6,4,2]

view::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::view::unique; // [1,2,3,1,2]

view::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::view::values; // [6,7]

view::zip

Ex.1 Lazily create tuples out of two or more ranges.
    auto const cities = std::vector<std::string> {"New York", "Moscow", "Berlin"};
    auto const population = std::vector<double> {8.6, 11.9, 3.5};
    auto rng = ranges::view::zip(cities, population);
    for (auto&& [first, second] : rng) {
         std::cout << first << ", " << second << '\n';
    }
    // New York, 8.6
    // Moscow, 11.9
    // Berlin, 3.5

view::zip_with

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::view::zip_with(
                     [](int a, int b){return a + b;}, v1, v2); // [7,4,8]