Skip to content

Instantly share code, notes, and snippets.

@przybylski
Created December 15, 2015 22:59
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 przybylski/afc1a96db4d3255ea05d to your computer and use it in GitHub Desktop.
Save przybylski/afc1a96db4d3255ea05d to your computer and use it in GitHub Desktop.
python style range and xrange in c++
#include <iterator>
#include <vector>
#include <cmath>
namespace btp {
template<typename T>
std::vector<T> range(T begin, T end, T step = 1) {
if (signbit(step) != signbit(end-begin)) return {};
std::vector<T> result;
if (begin <= end)
for (T i = begin; i < end; i += step)
result.push_back(i);
else
for (T i = begin; i > end; i += step)
result.push_back(i);
return result;
}
template<typename T>
std::vector<T> range(T end) { return range(T(0), end); }
namespace internal {
template<typename T>
class xrange_iterator : public std::iterator<std::forward_iterator_tag, T> {
T value_{T()};
T step_{T()};
bool forward_{true};
public:
xrange_iterator() {}
xrange_iterator(T value, T step, bool forward)
: value_(value),
step_(step),
forward_(forward)
{}
xrange_iterator(const xrange_iterator& rhs)
: value_(rhs.value_),
step_(rhs.step_),
forward_(rhs.forward_)
{}
xrange_iterator& operator=(const xrange_iterator& rhs) {
value_ = rhs.value_;
step_ = rhs.step_;
forward_ = rhs.forward_;
return *this;
}
xrange_iterator& operator++() { value_ += step_; return *this; }
xrange_iterator operator++(int) { xrange_iterator tmp(*this); operator++(); return tmp; }
bool operator==(const xrange_iterator& rhs) { return value_ == rhs.value_; }
bool operator!=(const xrange_iterator& rhs) { return forward_ == signbit(step_) ? false : forward_ ? value_ < rhs.value_ : value_ > rhs.value_; }
T& operator*() { return value_; }
};
template<typename T>
class xrange_impl {
T begin_, end_, step_;
const bool forward_;
public:
xrange_impl(T begin, T end, T step)
: begin_(begin),
end_(end),
step_(step),
forward_(begin < end)
{}
xrange_iterator<T> begin() { return xrange_iterator<T>(begin_, step_, forward_); }
xrange_iterator<T> end() { return xrange_iterator<T>(end_, step_, forward_); }
};
}
template<typename T>
internal::xrange_impl<T> xrange(T begin, T end, T step = 1) {
return internal::xrange_impl<T>(begin, end, step);
}
template<typename T>
internal::xrange_impl<T> xrange(T end) {
return xrange(T(0), end);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment