I found myself writing this just a bit ago:
template <long int T_begin, long int T_end> class range_class { public: class iterator { friend class range_class; public: long int operator *() const { return i_; } const iterator &operator ++() { ++i_; return *this; } iterator operator ++(int) { iterator copy(*this); ++i_; return copy; } bool operator ==(const iterator &other) const { return i_ == other.i_; } bool operator !=(const iterator &other) const { return i_ != other.i_; } protected: iterator(long int start) : i_ (start) { } private: unsigned long i_; }; iterator begin() const { return iterator(T_begin); } iterator end() const { return iterator(T_end); } }; template <long int T_begin, long int T_end> const range_class<T_begin, T_end> range() { return range_class<T_begin, T_end>(); }
And this allows me to write things like this:
for (auto i: range<0, 10>()) { // stuff with i }
Now, I know what I wrote is maybe not the best code. And maybe there's a way to make it more flexible and useful. But it seems to me like something like this should've been made part of the standard.
So is it? Was some sort of new library added for iterators over a range of integers, or maybe a generic range of computed scalar values?
Range-based for loop in C++ It executes a for loop over a range. Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.
Remarks. Use the range-based for statement to construct loops that must execute through a range, which is defined as anything that you can iterate through—for example, std::vector , or any other C++ Standard Library sequence whose range is defined by a begin() and end() .
Range-Based 'for' loops have been included in the language since C++11. It automatically iterates (loops) over the iterable (container). This is very efficient when used with the standard library container (as will be used in this article) as there will be no wrong access to memory outside the scope of the iterable.
Range-for is as fast as possible since it caches the end iterator[citationprovided], uses pre-increment and only dereferences the iterator once. Then, yes, range-for may be slightly faster, since it's also easier to write there's no reason not to use it (when appropriate).
The C++ standard library does not have one, but Boost.Range has boost::counting_range, which certainly qualifies. You could also use boost::irange, which is a bit more focused in scope.
C++20's range library will allow you to do this via view::iota(start, end)
.
As far as I know, there is no such class in C++11.
Anyway, I tried to improve your implementation. I made it non-template, as I don't see any advantage in making it template. On the contrary, it has one major disadvantage : that you cannot create the range at runtime, as you need to know the template arguments at compile time itself.
//your version auto x = range<m,n>(); //m and n must be known at compile time //my version auto x = range(m,n); //m and n may be known at runtime as well!
Here is the code:
class range { public: class iterator { friend class range; public: long int operator *() const { return i_; } const iterator &operator ++() { ++i_; return *this; } iterator operator ++(int) { iterator copy(*this); ++i_; return copy; } bool operator ==(const iterator &other) const { return i_ == other.i_; } bool operator !=(const iterator &other) const { return i_ != other.i_; } protected: iterator(long int start) : i_ (start) { } private: unsigned long i_; }; iterator begin() const { return begin_; } iterator end() const { return end_; } range(long int begin, long int end) : begin_(begin), end_(end) {} private: iterator begin_; iterator end_; };
Test code:
int main() { int m, n; std::istringstream in("10 20"); if ( in >> m >> n ) //using in, because std::cin cannot be used at coliru. { if ( m > n ) std::swap(m,n); for (auto i : range(m,n)) { std::cout << i << " "; } } else std::cout <<"invalid input"; }
Output:
10 11 12 13 14 15 16 17 18 19
Onine demo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With