Skip to content

Instantly share code, notes, and snippets.

@cjameshuff
Created August 16, 2016 21:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cjameshuff/7c57d1d0e0b4493b295af2f760abe275 to your computer and use it in GitHub Desktop.
Save cjameshuff/7c57d1d0e0b4493b295af2f760abe275 to your computer and use it in GitHub Desktop.
#include <cstdlib>
#include <iostream>
#include <iterator>
#include "boost/format.hpp"
using boost::format;
namespace iter {
template<typename T, int increment = 1>
class integer: public std::iterator<std::random_access_iterator_tag, const T>
{
public:
using value_type = const T;
protected:
T val;
public:
integer(value_type v = 0): val{v} {}
integer(const integer & rhs) = default;
auto operator++() -> integer & {val += increment; return *this;}
auto operator--() -> integer & {val -= increment; return *this;}
auto operator*() const -> value_type & {return val;}
auto operator==(const integer & rhs) const -> bool {return val == rhs.val;}
auto operator!=(const integer & rhs) const -> bool {return val != rhs.val;}
};
template<typename T>
class indexed:
public std::iterator<
typename std::iterator_traits<T>::iterator_category,
typename std::iterator_traits<T>::value_type,
typename std::iterator_traits<T>::difference_type,
typename std::iterator_traits<T>::pointer,
typename std::iterator_traits<T>::reference>
{
public:
struct value_type {
decltype(*(T())) value;
int index;
};
private:
T val;
int idx;
public:
indexed() {}
indexed(T v, int i = 0): val{v}, idx{i} {}
indexed(const indexed & rhs) = default;
auto operator++() -> indexed & {++val; ++idx; return *this;}
auto operator--() -> indexed & {--val; --idx; return *this;}
auto operator*() const -> value_type {return {*val, idx};}
auto operator==(const indexed & rhs) const -> bool {return val == rhs.val;}
auto operator!=(const indexed & rhs) const -> bool {return val != rhs.val;}
};
template<typename T, typename FnT, typename RetT>
class mapping:
public std::iterator<
typename std::iterator_traits<T>::iterator_category,
RetT,
typename std::iterator_traits<T>::difference_type,
typename std::iterator_traits<T>::pointer,
typename std::iterator_traits<T>::reference>
{
public:
using value_type = RetT;
private:
T val;
FnT fn;
public:
mapping() {}
mapping(T v, FnT f): val{v}, fn{f} {}
mapping(const mapping & rhs) = default;
auto operator++() -> mapping & {++val; return *this;}
auto operator*() const -> value_type {return fn(*val);}
auto operator==(const mapping & rhs) const -> bool {return val == rhs.val;}
auto operator!=(const mapping & rhs) const -> bool {return val != rhs.val;}
};
// template<typename T, typename FnT, typename RetT>
// class filter:
// public std::iterator<
// typename std::iterator_traits<T>::iterator_category,
// RetT,
// typename std::iterator_traits<T>::difference_type,
// typename std::iterator_traits<T>::pointer,
// typename std::iterator_traits<T>::reference>
// {
// public:
// using value_type = RetT;
// private:
// T val;
// FnT fn;
// public:
// filter() {}
// filter(T v, FnT f): val{v}, fn{f} {}
// filter(const filter & rhs) = default;
// auto operator++() -> filter & {
// ++val;
// return *this;
// }
// auto operator*() const -> value_type {return fn(*val);}
// auto operator==(const filter & rhs) const -> bool {return val == rhs.val;}
// auto operator!=(const filter & rhs) const -> bool {return val != rhs.val;}
// };
}// namespace iter
// Little more than a wrapper for a begin/end pair.
// Ranges can be created from any entity that supports the begin()/end() interface.
template<typename T>
class range {
public:
using iterator = T;
using value_type = decltype(*(T()));
private:
iterator begin_val;
iterator end_val;
public:
range(iterator b, iterator e): begin_val{b}, end_val{e} {}
range(const range & rhs) = default;
auto begin() const -> iterator {return begin_val;}
auto end() const -> iterator {return end_val;}
auto subrange(size_t a, size_t b) const -> range<T> {return {begin_val + a, begin_val + b};}
auto size() const -> size_t {return end_val - begin_val;}
auto reverse() const -> range<std::reverse_iterator<iterator>> {
return {std::reverse_iterator<iterator>{end_val},
std::reverse_iterator<iterator>{begin_val}};
}
auto indexed(int start_idx = 0) const -> range<iter::indexed<iterator>> {
return {{begin_val, start_idx}, {end_val, 0}};
}
template<typename FnT>
auto map(FnT fn) const -> range<iter::mapping<iterator, FnT, decltype(fn(*begin_val))>> {
return {{begin_val, fn}, {end_val, fn}};
}
// template<typename FnT>
// auto filter(FnT fn) const -> range<iter::filter<iterator, FnT>> {
// return {{begin_val, fn}, {end_val, fn}};
// }
/// Range must not be empty. Function takes and returns arguments of range value_type.
template<typename FnT>
auto fold(FnT fn) const -> decltype(fn(*begin_val, *begin_val)) {
auto accum = *begin_val;
for(auto x: range<T>{begin_val+1, end_val})
accum = fn(accum, x);
return accum;
}
/// Range may be empty. Function takes arguments of type T2 and range value_type, and returns
/// type T2.
template<typename T2, typename FnT>
auto fold(T2 init_val, FnT fn) const -> T2 {
auto accum = init_val;
for(auto x: *this)
accum = fn(accum, x);
return accum;
}
};
template<typename T>
auto gen_range(const T & cont) -> range<typename T::const_iterator> {
using std::begin;
using std::end;
return {begin(cont), end(cont)};
}
using irange = range<iter::integer<int, 1>>;
int main()
{
auto strings = std::array<std::string, 5>{"foo", "bar", "glib", "glob", "gnop"};
for(auto x: irange{0, 10})
std::cout << x << std::endl;
std::cout << std::endl;
for(auto x: irange{0, 10}.reverse())
std::cout << x << std::endl;
std::cout << std::endl;
for(auto x: strings)
std::cout << x << std::endl;
std::cout << std::endl;
for(auto x: gen_range(strings))
std::cout << x << std::endl;
std::cout << std::endl;
for(auto x: gen_range(strings).reverse())
std::cout << x << std::endl;
std::cout << std::endl;
for(auto x: gen_range(strings).indexed())
std::cout << x.index << ": " << x.value << std::endl;
std::cout << std::endl;
// for(auto x: irange{0, 10})
for(auto x: irange{0, 10}.map([](int x)-> std::string {return str(format("x*x: %d")%(x*x));}))
std::cout << x << std::endl;
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment