#include #include #include #include #include #include #include template class range { public: using value_type = typename Container::value_type; using iterator = typename Container::iterator; range(iterator const& first, iterator const& last) : first{first}, last{last} { } iterator begin() { return first; } iterator end() { return last; } int size() const { return std::distance(first, last); } range take(int n) { return range{first, std::next(first, n)}; } range skip(int n) { return range{std::next(first, n), last}; } private: iterator first; iterator last; }; template range make_range(Container& c) { return range{c.begin(), c.end()}; } template range& map(range& r, Operator op) { std::transform(r.begin(), r.end(), r.begin(), op); return r; } template range& filter(range& r, Predicate pred) { auto it {std::remove_if(r.begin(), r.end(), pred)}; r = range{r.begin(), it}; return r; } template auto reduce(range& r, typename range::value_type initial, Operator op) { return std::accumulate(r.begin(), r.end(), initial, op); } int main() { { // test reduce, map, and filter std::list v { 1, 2, 3, 4, 5, 6 }; auto r {make_range(v)}; assert(reduce(map(filter(r, [](int n) { return n % 2 == 0; }), [](int n) { return 2 * n; }), 0.0, [](int n, int m) { return n + m; }) == 18); } { // test size, filter and range-based for-loop std::vector v { -2.6, 7.0, 1.3, 15.2 }; auto r {make_range(v)}; assert(r.size() == 4); filter(r, [](double x) { return x < 0.0; }); assert(r.size() == 3); int i{0}; for (double x : r) { assert(x == v.at(i++)); } } { // test take and skip std::forward_list v { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; auto r {make_range(v)}; int n{0}; for (int x : r.take(3)) { assert(x == n++); } for (int x : r.skip(3)) { assert(x == n++); } } }