Range-v3 Range algorithms, views, and actions for the Standard Library
Examples

# Examples: Algorithms

## Hello, Ranges!

#include <iostream>
#include <range/v3/all.hpp> // get everything
#include <string>
using std::cout;
int
main()
{
std::string s{"hello"};
// output: h e l l o
ranges::for_each(s, [](char c) { cout << c << ' '; });
cout << '\n';
}

## any_of, all_of, none_of

// Demonstrates any_of, all_of, none_of
// output
// vector: [6,2,3,4,5,6]
// vector any_of is_six: true
// vector all_of is_six: false
// vector none_of is_six: false
#include <iostream>
#include <vector>
using std::cout;
auto is_six = [](int i) { return i == 6; };
int
main()
{
std::vector<int> v{6, 2, 3, 4, 5, 6};
cout << std::boolalpha;
cout << "vector: " << ranges::views::all(v) << '\n';
cout << "vector any_of is_six: " << ranges::any_of(v, is_six) << '\n';
cout << "vector all_of is_six: " << ranges::all_of(v, is_six) << '\n';
cout << "vector none_of is_six: " << ranges::none_of(v, is_six) << '\n';
}

## count

// This example demonstrates counting the number of
// elements that match a given value.
// output...
// vector: 2
// array: 2
#include <iostream>
#include <range/v3/algorithm/count.hpp> // specific includes
#include <vector>
using std::cout;
int
main()
{
std::vector<int> v{6, 2, 3, 4, 5, 6};
// note the count return is a numeric type
// like int or long -- auto below make sure
// it matches the implementation
auto c = ranges::count(v, 6);
cout << "vector: " << c << '\n';
std::array<int, 6> a{6, 2, 3, 4, 5, 6};
c = ranges::count(a, 6);
cout << "array: " << c << '\n';
}

## count_if

// This example counts element of a range that match a supplied predicate.
// output
// vector: 2
// array: 2
#include <array>
#include <iostream>
#include <range/v3/algorithm/count_if.hpp> // specific includes
#include <vector>
using std::cout;
auto is_six = [](int i) -> bool { return i == 6; };
int
main()
{
std::vector<int> v{6, 2, 3, 4, 5, 6};
auto c = ranges::count_if(v, is_six);
cout << "vector: " << c << '\n'; // 2
std::array<int, 6> a{6, 2, 3, 4, 5, 6};
c = ranges::count_if(a, is_six);
cout << "array: " << c << '\n'; // 2
}

## find, find_if, find_if_not on sequence containers

// vector: *i: 6
// didn't find 10
// *i: 6
// *i: 2
// *i after ++ (2 expected): 2
// array: *i: 6
// list: *i: 6
// fwd_list: *i: 4
// deque: *i: 6
#include <array>
#include <deque>
#include <forward_list>
#include <iostream>
#include <list>
#include <range/v3/all.hpp>
#include <vector>
using std::cout;
auto is_six = [](int i) -> bool { return i == 6; };
int
main()
{
cout << "vector: ";
std::vector<int> v{6, 2, 6, 4, 6, 1};
{
auto i = ranges::find(v, 6); // 1 2 3 4 5 6
cout << "*i: " << *i << '\n';
}
{
auto i = ranges::find(v, 10); // 1 2 3 4 5 6
if(i == ranges::end(v))
{
cout << "didn't find 10\n";
}
}
{
auto i = ranges::find_if(v, is_six);
if(i != ranges::end(v))
{
cout << "*i: " << *i << '\n';
}
}
{
auto i = ranges::find_if_not(v, is_six);
if(i != ranges::end(v))
{
cout << "*i: " << *i << '\n';
}
}
{
auto i = ranges::find(v, 6);
i++;
if(i != ranges::end(v))
{
cout << "*i after ++ (2 expected): " << *i;
}
}
cout << "\narray: ";
std::array<int, 6> a{6, 2, 3, 4, 5, 1};
{
auto i = ranges::find(a, 6);
if(i != ranges::end(a))
{
cout << "*i: " << *i;
}
}
cout << "\nlist: ";
std::list<int> li{6, 2, 3, 4, 5, 1};
{
auto i = ranges::find(li, 6);
if(i != ranges::end(li))
{
cout << "*i: " << *i;
}
}
cout << "\nfwd_list: ";
std::forward_list<int> fl{6, 2, 3, 4, 5, 1};
{
auto i = ranges::find(fl, 4);
if(i != ranges::end(fl))
{
cout << "*i: " << *i;
}
}
cout << "\ndeque: ";
std::deque<int> d{6, 2, 3, 4, 5, 1};
{
auto i = ranges::find(d, 6);
if(i != ranges::end(d))
{
cout << "*i: " << *i;
}
}
cout << '\n';
}

## for_each on sequence containers

// Use the for_each to print from various containers
// output
// vector: 1 2 3 4 5 6
// array: 1 2 3 4 5 6
// list: 1 2 3 4 5 6
// fwd_list: 1 2 3 4 5 6
// deque: 1 2 3 4 5 6
#include <array>
#include <deque>
#include <forward_list>
#include <iostream>
#include <list>
#include <queue>
#include <range/v3/algorithm/for_each.hpp> // specific includes
#include <stack>
#include <vector>
using std::cout;
auto print = [](int i) { cout << i << ' '; };
int
main()
{
cout << "vector: ";
std::vector<int> v{1, 2, 3, 4, 5, 6};
ranges::for_each(v, print); // 1 2 3 4 5 6
cout << "\narray: ";
std::array<int, 6> a{1, 2, 3, 4, 5, 6};
ranges::for_each(a, print);
cout << "\nlist: ";
std::list<int> ll{1, 2, 3, 4, 5, 6};
ranges::for_each(ll, print);
cout << "\nfwd_list: ";
std::forward_list<int> fl{1, 2, 3, 4, 5, 6};
ranges::for_each(fl, print);
cout << "\ndeque: ";
std::deque<int> d{1, 2, 3, 4, 5, 6};
ranges::for_each(d, print);
cout << '\n';
}

## for_each on associative containers

// for_each with associative containers
// output
// set: 1 2 3 4 5 6
// map: one:1 three:3 two:2
// unordered_map: three:3 one:1 two:2
// unordered_set: 6 5 4 3 2 1
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
using std::cout;
using std::string;
auto print = [](int i) { cout << i << ' '; };
// must take a pair for map types
auto printm = [](std::pair<string, int> p) {
cout << p.first << ":" << p.second << ' ';
};
int
main()
{
cout << "set: ";
std::set<int> si{1, 2, 3, 4, 5, 6};
ranges::for_each(si, print);
cout << "\nmap: ";
std::map<string, int> msi{{"one", 1}, {"two", 2}, {"three", 3}};
ranges::for_each(msi, printm);
cout << "\nunordered map: ";
std::unordered_map<string, int> umsi{{"one", 1}, {"two", 2}, {"three", 3}};
ranges::for_each(umsi, printm);
cout << "\nunordered set: ";
std::unordered_set<int> usi{1, 2, 3, 4, 5, 6};
ranges::for_each(usi, print);
cout << '\n';
}

## is_sorted

// Check if a container is sorted
// output
// vector: true
// array: false
#include <array>
#include <iostream>
#include <range/v3/algorithm/is_sorted.hpp> // specific includes
#include <vector>
using std::cout;
int
main()
{
cout << std::boolalpha;
std::vector<int> v{1, 2, 3, 4, 5, 6};
cout << "vector: " << ranges::is_sorted(v) << '\n';
std::array<int, 6> a{6, 2, 3, 4, 5, 6};
cout << "array: " << ranges::is_sorted(a) << '\n';
}

# Examples: Views

## Filter and transform

// This example demonstrates filtering and transforming a range on the
#include <iostream>
#include <string>
#include <vector>
using std::cout;
int main()
{
std::vector<int> const vi{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
using namespace ranges;
auto rng = vi | views::filter([](int i) { return i % 2 == 0; }) |
views::transform([](int i) { return std::to_string(i); });
// prints: [2,4,6,8,10]
cout << rng << '\n';
}

## Generate ints and accumulate

// Sums the first ten squares and prints them, using views::ints to generate
// and infinite range of integers, views::transform to square them, views::take
// to drop all but the first 10, and accumulate to sum them.
#include <iostream>
#include <vector>
using std::cout;
int main()
{
using namespace ranges;
int sum = accumulate(views::ints(1, unreachable) | views::transform([](int i) {
return i * i;
}) | views::take(10),
0);
// prints: 385
cout << sum << '\n';
}

## Convert a range comprehension to a vector

// Use a range comprehension (views::for_each) to construct a custom range, and
// then convert it to a std::vector.
#include <iostream>
#include <vector>
using std::cout;
int main()
{
using namespace ranges;
auto vi = views::for_each(views::ints(1, 6),
[](int i) { return yield_from(views::repeat_n(i, i)); }) |
to<std::vector>();
// prints: [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
cout << views::all(vi) << '\n';
}

# Examples: Actions

## Remove non-unique elements from a container

// Remove all non-unique elements from a container.
#include <iostream>
#include <vector>
using std::cout;
int main()
{
std::vector<int> vi{9, 4, 5, 2, 9, 1, 0, 2, 6, 7, 4, 5, 6, 5, 9, 2, 7,
1, 4, 5, 3, 8, 5, 0, 2, 9, 3, 7, 5, 7, 5, 5, 6, 1,
4, 3, 1, 8, 4, 0, 7, 8, 8, 2, 6, 5, 3, 4, 5};
using namespace ranges;
// prints: [0,1,2,3,4,5,6,7,8,9]
cout << views::all(vi) << '\n';
}

# Examples: Putting it all together

## Calendar

// Usage:
// calendar 2015
//
// Output:
/*
January February March
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 7
4 5 6 7 8 9 10 8 9 10 11 12 13 14 8 9 10 11 12 13 14
11 12 13 14 15 16 17 15 16 17 18 19 20 21 15 16 17 18 19 20 21
18 19 20 21 22 23 24 22 23 24 25 26 27 28 22 23 24 25 26 27 28
25 26 27 28 29 30 31 29 30 31
April May June
1 2 3 4 1 2 1 2 3 4 5 6
5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
31
July August September
1 2 3 4 1 1 2 3 4 5
5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12
12 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19
19 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26
26 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30
30 31
October November December
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5
4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12
11 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19
18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26
25 26 27 28 29 30 31 29 30 27 28 29 30 31
// */
// Credits:
// Thanks to H. S. Teoh for the article that served as the
// inspiration for this example:
// <http://wiki.dlang.org/Component_programming_with_ranges>
// Thanks to github's Arzar for bringing date::week_number
// to my attention.
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp>
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iostream>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
namespace po = boost::program_options;
namespace greg = boost::gregorian;
using date = greg::date;
using day = greg::date_duration;
using namespace ranges;
namespace boost
{
namespace gregorian
{
date &operator++(date &d)
{
return d = d + day(1);
}
date operator++(date &d, int)
{
return ++d - day(1);
}
}
}
namespace ranges
{
template<>
struct incrementable_traits<date>
{
using difference_type = date::duration_type::duration_rep::int_type;
};
}
CPP_assert(incrementable<date>);
auto
dates(unsigned short start, unsigned short stop)
{
return views::iota(date{start, greg::Jan, 1}, date{stop, greg::Jan, 1});
}
auto
dates_from(unsigned short year)
{
return views::iota(date{year, greg::Jan, 1});
}
auto
by_month()
{
return views::group_by(
[](date a, date b) { return a.month() == b.month(); });
}
auto
by_week()
{
return views::group_by([](date a, date b) {
// ++a because week_number is Mon-Sun and we want Sun-Sat
return (++a).week_number() == (++b).week_number();
});
}
std::string
format_day(date d)
{
return boost::str(boost::format("%|3|") % d.day());
}
// In: range<range<date>>: month grouped by weeks.
// Out: range<std::string>: month with formatted weeks.
auto
format_weeks()
{
return views::transform([](/*range<date>*/ auto week) {
return boost::str(boost::format("%1%%2%%|22t|") %
std::string(front(week).day_of_week() * 3u, ' ') %
(week | views::transform(format_day) | actions::join));
});
}
// Return a formatted string with the title of the month
// corresponding to a date.
std::string
month_title(date d)
{
return boost::str(boost::format("%|=22|") % d.month().as_long_string());
}
// In: range<range<date>>: year of months of days
// Out: range<range<std::string>>: year of months of formatted wks
auto
layout_months()
{
return views::transform([](/*range<date>*/ auto month) {
auto week_count =
static_cast<std::ptrdiff_t>(distance(month | by_week()));
return views::concat(
views::single(month_title(front(month))),
month | by_week() | format_weeks(),
views::repeat_n(std::string(22, ' '), 6 - week_count));
});
}
// Flattens a range of ranges by iterating the inner
// ranges in round-robin fashion.
template<class Rngs>
{
friend range_access;
std::vector<range_value_t<Rngs>> rngs_;
struct cursor;
cursor begin_cursor()
{
return {0, &rngs_, views::transform(rngs_, ranges::begin) | to<std::vector>};
}
public:
interleave_view() = default;
explicit interleave_view(Rngs rngs)
: rngs_(std::move(rngs) | to<std::vector>)
{}
};
template<class Rngs>
struct interleave_view<Rngs>::cursor
{
std::vector<range_value_t<Rngs>> *rngs_;
std::vector<iterator_t<range_value_t<Rngs>>> its_;
{
return *its_[n_];
}
void next()
{
if(0 == ((++n_) %= its_.size()))
for_each(its_, [](auto &it) { ++it; });
}
{
if(n_ != 0)
return false;
auto ends = *rngs_ | views::transform(ranges::end);
return its_.end() != std::mismatch(
its_.begin(), its_.end(), ends.begin(), std::not_equal_to<>{}).first;
}
CPP_member
auto equal(cursor const& that) const -> CPP_ret(bool)(
requires forward_range<range_value_t<Rngs>>)
{
return n_ == that.n_ && its_ == that.its_;
}
};
// In: range<range<T>>
// Out: range<T>, flattened by walking the ranges
// round-robin fashion.
auto
interleave()
{
return make_view_closure([](auto &&rngs) {
using Rngs = decltype(rngs);
return interleave_view<views::all_t<Rngs>>(
views::all(std::forward<Rngs>(rngs)));
});
}
// In: range<range<T>>
// Out: range<range<T>>, transposing the rows and columns.
auto
{
return make_view_closure([](auto &&rngs) {
using Rngs = decltype(rngs);
CPP_assert(forward_range<Rngs>);
return std::forward<Rngs>(rngs)
| interleave()
| views::chunk(static_cast<std::size_t>(distance(rngs)));
});
}
// In: range<range<range<string>>>
// Out: range<range<range<string>>>, transposing months.
auto
transpose_months()
{
[](/*range<range<string>>*/ auto rng) { return rng | transpose(); });
}
// In: range<range<string>>
// Out: range<string>, joining the strings of the inner ranges
auto
join_months()
{
[](/*range<string>*/ auto rng) { return actions::join(rng); });
}
// In: range<date>
// Out: range<string>, lines of formatted output
auto
format_calendar(std::size_t months_per_line)
{
return
// Group the dates by month:
by_month()
// Format the month into a range of strings:
| layout_months()
// Group the months that belong side-by-side:
| views::chunk(months_per_line)
// Transpose the rows and columns of the size-by-side months:
| transpose_months()
// Ungroup the side-by-side months:
// Join the strings of the transposed months:
| join_months();
}
int
main(int argc, char *argv[]) try
{
// Declare the supported options.
po::options_description desc("Allowed options");
"start", po::value<unsigned short>(), "Year to start")(
"stop", po::value<std::string>(), "Year to stop")(
"per-line",
po::value<std::size_t>()->default_value(3u),
"Nbr of months per line");
po::positional_options_description p;
po::variables_map vm;
po::store(
po::command_line_parser(argc, argv).options(desc).positional(p).run(),
vm);
po::notify(vm);
if(vm.count("help") || 1 != vm.count("start"))
{
std::cerr << desc << '\n';
return 1;
}
auto const start = vm["start"].as<unsigned short>();
auto const stop = 0 == vm.count("stop")
? (unsigned short)(start + 1)
: vm["stop"].as<std::string>() == "never"
? (unsigned short)-1
: boost::lexical_cast<unsigned short>(
vm["stop"].as<std::string>());
auto const months_per_line = vm["per-line"].as<std::size_t>();
if(stop != (unsigned short)-1 && stop <= start)
{
std::cerr << "ERROR: The stop year must be larger than the start"
<< '\n';
return 1;
}
if((unsigned short)-1 != stop)
{
copy(dates(start, stop) | format_calendar(months_per_line),
ostream_iterator<>(std::cout, "\n"));
}
else
{
copy(dates_from(start) | format_calendar(months_per_line),
ostream_iterator<>(std::cout, "\n"));
}
}
catch(std::exception &e)
{
std::cerr << "ERROR: Unhandled exception\n";
std::cerr << " what(): " << e.what();
return 1;
}
filter.hpp
join.hpp
ranges::ostream_iterator
Definition: stream_iterators.hpp:30
any_of.hpp
meta::transpose
fold< ListOfLists, repeat_n< size< front< ListOfLists > >, list<> >, bind_back< quote< transform >, quote< push_back > >> transpose
Given a list of lists of types ListOfLists, transpose the elements from the lists.
Definition: meta.hpp:2338
unique.hpp
for_each.hpp
ranges::next
constexpr next_fn next
Definition: operations.hpp:181
ranges::aux::copy
constexpr copy_fn copy
Definition: copy.hpp:53
ranges::to
auto to() -> detail::to_container_fn< detail::from_range< ContT >>
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:394
meta::front
_t< detail::front_< L > > front
Return the first element in meta::list L.
Definition: meta.hpp:1663
meta::for_each
constexpr detail::for_each_fn for_each
for_each(L, Fn) calls the Fn for each argument in the L.
Definition: meta.hpp:2328
transform.hpp
meta::accumulate
fold< L, State, Fn > accumulate
An alias for meta::fold.
Definition: meta.hpp:1229
conversion.hpp
group_by.hpp
meta::count
_t< detail::count_< L, T > > count
Count the number of times a type T appears in the list L.
Definition: meta.hpp:2215
count_if.hpp
chunk.hpp
all_of.hpp
count.hpp
meta::count_if
_t< detail::count_if_< L, Fn > > count_if
Count the number of times the predicate Fn evaluates to true for all the elements in the list L.
Definition: meta.hpp:2249
meta::find
drop< L, min< find_index< L, T >, size< L > >> find
Return the tail of the list L starting at the first occurrence of T, if any such element exists; the ...
Definition: meta.hpp:1981
ranges::mismatch
mismatch_result< I1, I2 > mismatch(I1 begin1, S1 end1, I2 begin2, C pred=C{}, P1 proj1=P1{}, P2 proj2=P2{})
function template mismatch
Definition: mismatch.hpp:39
repeat_n.hpp
sort.hpp
accumulate.hpp
join.hpp
meta::size_t
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:161
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition: range_fwd.hpp:426
all.hpp
concat.hpp
ranges::equal
constexpr bool equal(I0 begin0, S0 end0, I1 begin1, C pred=C{}, P0 proj0=P0{}, P1 proj1=P1{})
function template equal
Definition: equal.hpp:54
copy.hpp
ranges::incrementable_traits
Definition: range_fwd.hpp:166
ranges::find_if_not
I find_if_not(I first, S last, F pred, P proj=P{})
template function find_if_not
Definition: find_if_not.hpp:44
ranges::default_sentinel_t
Definition: default_sentinel.hpp:24
iota.hpp
is_sorted.hpp
take.hpp
for_each.hpp
ranges::end
constexpr _end_::fn end
Definition: access.hpp:326
ranges::begin
constexpr _begin_::fn begin
Definition: access.hpp:181
ranges::make_view_closure
constexpr make_view_closure_fn make_view_closure
Definition: view.hpp:88
meta::sort
_t< detail::sort_< L, Fn > > sort
Return a new meta::list that is sorted according to invocable predicate Fn.
Definition: meta.hpp:2722
unique
constexpr action_closure< unique_fn > unique
Definition: unique.hpp:58
meta::find_if
_t< detail::find_if_< L, Fn > > find_if
Return the tail of the list L starting at the first element A such that invoke<Fn,...
Definition: meta.hpp:2069
none_of.hpp
single.hpp
ranges::is_sorted
bool is_sorted(I first, S last, R rel=R{}, P proj=P{})
template function is_sorted
Definition: is_sorted.hpp:49
ranges::distance
constexpr distance_fn distance
Definition: operations.hpp:459
core.hpp
meta::any_of
not_< empty< find_if< L, Fn > >> any_of
A Boolean integral constant wrapper around true if invoke<Fn, A>::value is true for any element A in ...
Definition: meta.hpp:2491
stream_iterators.hpp
meta::filter
join< transform< L, detail::filter_< Pred > >> filter
Returns a new meta::list where only those elements of L that satisfy the Callable Pred such that invo...
Definition: meta.hpp:2280
meta::repeat_n
repeat_n_c< N::type::value, T > repeat_n
Generate list<T,T,T...T> of size N arguments.
Definition: meta.hpp:1504
ranges::aux::move
constexpr move_fn move
Definition: move.hpp:49
meta::none_of
empty< find_if< L, Fn > > none_of
A Boolean integral constant wrapper around true if invoke<Fn, A>::value is false for all elements A i...
Definition: meta.hpp:2509
mismatch.hpp
meta::all_of
empty< find_if< L, not_fn< Fn > >> all_of
A Boolean integral constant wrapper around true if invoke<Fn, A>::value is true for all elements A in...
Definition: meta.hpp:2473
meta::transform
_t< detail::transform_< Args... > > transform
Return a new meta::list constructed by transforming all the elements in L with the unary invocable Fn...
Definition: meta.hpp:1457
meta::join
apply< quote< concat >, ListOfLists > join
Joins a list of lists into a single list.
Definition: meta.hpp:1410
all.hpp