Created
December 15, 2015 22:59
-
-
Save przybylski/afc1a96db4d3255ea05d to your computer and use it in GitHub Desktop.
python style range and xrange in c++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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