Skip to content

Instantly share code, notes, and snippets.

@cglosser
Last active February 8, 2018 15:41
Show Gist options
  • Save cglosser/9dc68a7aa6eab361352402660fafe82a to your computer and use it in GitHub Desktop.
Save cglosser/9dc68a7aa6eab361352402660fafe82a to your computer and use it in GitHub Desktop.
Stateful, python-like ranges and enumerations for C++ iterables
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
template <class T>
class Range {
public:
Range(const T upper) : Range(0, upper, 1) {}
Range(const T lower, const T upper) : Range(lower, upper, 1) {}
Range(const T lower, const T upper, const T step)
: lower_(lower), upper_(upper), step_(step) {}
class iterator {
public:
iterator(const Range &r, const T val) : owner_(r), val_(val) {}
T operator*() const { return val_; }
bool operator!=(const iterator &other) const { return val_ < other.val_; }
iterator operator++() {
val_ += owner_.step_;
return *this;
}
iterator reset() {
val_ = lower_;
return *this;
}
private:
const Range &owner_;
T val_;
};
iterator begin() const { return iterator(*this, lower_); }
iterator end() const { return iterator(*this, upper_); }
private:
T lower_, upper_, step_;
};
template <class T>
Range<T> range(T low, T up, T step) {
return Range<T>(low, up, step);
}
template <class T>
class Range3D {
public:
Range3D(const T max) : Range3D({max, max}, {max, max}, {max, max}) {}
Range3D(std::pair<T, T> xbounds, std::pair<T, T> ybounds,
std::pair<T, T> zbounds)
: xbounds_{xbounds}, ybounds_{ybounds}, zbounds_{zbounds} {}
class iterator {
public:
iterator(const Range3D &r, const T x, const T y, const T z)
: owner_{r}, x_{x}, y_{y}, z_{z} {}
const iterator &operator*() const { return *this; }
bool operator!=(const iterator &other) const {
return x_ != other.x_ && y_ != other.y_ && z_ != other.z_;
}
iterator operator++() {
++z_;
if (z_ == owner_.zbounds_.second) {
z_ = owner_.zbounds_.first;
++y_;
if (y_ == owner_.ybounds_.second) {
y_ = owner_.ybounds_.first;
++x_;
}
}
return *this;
}
T x() const { return x_; }
T y() const { return y_; }
T z() const { return z_; }
private:
const Range3D &owner_;
T x_, y_, z_;
};
iterator begin() const {
return iterator{*this, xbounds_.first, ybounds_.first, zbounds_.first};
}
iterator end() const {
return iterator{*this, xbounds_.second, ybounds_.second, zbounds_.second};
}
private:
std::pair<T, T> xbounds_, ybounds_, zbounds_;
};
template <class T, class U>
class Enumeration {
public:
Enumeration(const T &begin, const T &end) : Enumeration(begin, end, 0) {}
Enumeration(const T &begin, const T &end, int start_idx)
: begin_{begin}, end_{end}, start_idx_{start_idx} {};
class iterator {
public:
iterator(const Enumeration &e, const T val)
: owner_(e), val_(val), idx_(e.start_idx_) {}
iterator operator*() const { return *this; }
bool operator!=(const iterator &other) const { return val_ != other.val_; }
iterator operator++() {
++val_;
++idx_;
return *this;
}
int idx() const { return idx_; }
U value() const { return *val_; }
private:
const Enumeration &owner_;
T val_;
int idx_;
};
iterator begin() { return iterator{*this, begin_}; }
iterator end() { return iterator{*this, end_}; }
private:
T begin_, end_;
int start_idx_;
};
template <class T>
auto enumerate(const T &begin, const T &end, int i0 = 0) {
return Enumeration<T, decltype(*begin)>(begin, end, i0);
}
int main() {
std::vector<int> x{10, 20, 30, 40, 50};
for (const auto &e : enumerate(x.begin(), x.end())) {
std::cout << e.idx() << " " << e.value() << std::endl;
}
std::cout << std::endl;
std::set<int> y{10, 20, 3, 3, 40, 10, 50};
for (const auto &e : enumerate(y.begin(), y.end())) {
std::cout << e.idx() << " " << e.value() << std::endl;
}
std::cout << std::endl;
std::string s{"The cake is a lie!"};
for (const auto &e : enumerate(s.begin(), s.end())) {
std::cout << e.idx() << " " << e.value() << std::endl;
}
for(const auto &i : Range3D<int>({0, 3}, {0, 3}, {0, 3})) {
std::cout << i.x() << " " << i.y() << " " << i.z() << std::endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment