Examples: Algorithms
Hello, Ranges!
#include <iostream>
#include <string>
using std::cout;
int
main()
{
std::string s{"hello"};
cout << '\n';
}
any_of, all_of, none_of
#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';
}
count
#include <iostream>
#include <vector>
using std::cout;
int
main()
{
std::vector<int> v{6, 2, 3, 4, 5, 6};
cout << "vector: " << c << '\n';
std::array<int, 6> a{6, 2, 3, 4, 5, 6};
cout << "array: " << c << '\n';
}
count_if
#include <array>
#include <iostream>
#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};
cout << "vector: " << c << '\n';
std::array<int, 6> a{6, 2, 3, 4, 5, 6};
cout << "array: " << c << '\n';
}
find, find_if, find_if_not on sequence containers
#include <array>
#include <deque>
#include <forward_list>
#include <iostream>
#include <list>
#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};
{
cout << "*i: " << *i << '\n';
}
{
{
cout << "didn't find 10\n";
}
}
{
{
cout << "*i: " << *i << '\n';
}
}
{
{
cout << "*i: " << *i << '\n';
}
}
{
i++;
{
cout << "*i after ++ (2 expected): " << *i;
}
}
cout << "\narray: ";
std::array<int, 6> a{6, 2, 3, 4, 5, 1};
{
{
cout << "*i: " << *i;
}
}
cout << "\nlist: ";
std::list<int> li{6, 2, 3, 4, 5, 1};
{
{
cout << "*i: " << *i;
}
}
cout << "\nfwd_list: ";
std::forward_list<int> fl{6, 2, 3, 4, 5, 1};
{
{
cout << "*i: " << *i;
}
}
cout << "\ndeque: ";
std::deque<int> d{6, 2, 3, 4, 5, 1};
{
{
cout << "*i: " << *i;
}
}
cout << '\n';
}
for_each on sequence containers
#include <array>
#include <deque>
#include <forward_list>
#include <iostream>
#include <list>
#include <queue>
#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};
cout << "\narray: ";
std::array<int, 6> a{1, 2, 3, 4, 5, 6};
cout << "\nlist: ";
std::list<int> ll{1, 2, 3, 4, 5, 6};
cout << "\nfwd_list: ";
std::forward_list<int> fl{1, 2, 3, 4, 5, 6};
cout << "\ndeque: ";
std::deque<int> d{1, 2, 3, 4, 5, 6};
cout << '\n';
}
for_each on associative containers
#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 << ' '; };
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};
cout << "\nmap: ";
std::map<string, int> msi{{"one", 1}, {"two", 2}, {"three", 3}};
cout << "\nunordered map: ";
std::unordered_map<string, int> umsi{{"one", 1}, {"two", 2}, {"three", 3}};
cout << "\nunordered set: ";
std::unordered_set<int> usi{1, 2, 3, 4, 5, 6};
cout << '\n';
}
is_sorted
#include <array>
#include <iostream>
#include <vector>
using std::cout;
int
main()
{
cout << std::boolalpha;
std::vector<int> v{1, 2, 3, 4, 5, 6};
std::array<int, 6> a{6, 2, 3, 4, 5, 6};
}
Examples: Views
Filter and transform
#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; }) |
cout << rng << '\n';
}
Generate ints and accumulate
#include <iostream>
#include <vector>
using std::cout;
int main()
{
using namespace ranges;
return i * i;
}) | views::take(10),
0);
cout << sum << '\n';
}
Convert a range comprehension to a vector
#include <iostream>
#include <vector>
using std::cout;
int main()
{
using namespace ranges;
to<std::vector>();
cout << views::all(vi) << '\n';
}
Examples: Actions
Remove 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;
cout << views::all(vi) << '\n';
}
Examples: Putting it all together
Calendar
#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<>
{
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) {
return (++a).week_number() == (++b).week_number();
});
}
std::string
format_day(date d)
{
return boost::str(boost::format("%|3|") % d.day());
}
auto
format_weeks()
{
return boost::str(boost::format("%1%%2%%|22t|") %
std::string(
front(week).day_of_week() * 3u,
' ') %
});
}
std::string
month_title(date d)
{
return boost::str(boost::format("%|=22|") % d.month().as_long_string());
}
auto
layout_months()
{
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(),
});
}
template<class Rngs>
class interleave_view :
public view_facade<interleave_view<Rngs>>
{
friend range_access;
std::vector<range_value_t<Rngs>> rngs_;
struct cursor;
cursor begin_cursor()
{
}
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_;
decltype(auto) read() const
{
return *its_[n_];
}
{
if(0 == ((++n_) %= its_.size()))
}
{
if(n_ != 0)
return false;
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_;
}
};
auto
interleave()
{
using Rngs = decltype(rngs);
return interleave_view<views::all_t<Rngs>>(
views::all(std::forward<Rngs>(rngs)));
});
}
auto
{
using Rngs = decltype(rngs);
CPP_assert(forward_range<Rngs>);
return std::forward<Rngs>(rngs)
| interleave()
});
}
auto
transpose_months()
{
[](
auto rng) {
return rng |
transpose(); });
}
auto
join_months()
{
}
auto
{
return
by_month()
| layout_months()
| views::chunk(months_per_line)
| transpose_months()
| join_months();
}
int
main(int argc, char *argv[]) try
{
po::options_description desc("Allowed options");
desc.add_options()("help", "produce help message")(
"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;
p.add("start", 1).add("stop", 1);
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),
}
else
{
copy(dates_from(start) | format_calendar(months_per_line),
}
}
catch(std::exception &e)
{
std::cerr << "ERROR: Unhandled exception\n";
std::cerr << " what(): " << e.what();
return 1;
}