Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a range class in C++11 for use with range based for loops?

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?

like image 750
Omnifarious Avatar asked Aug 25 '11 05:08

Omnifarious


People also ask

Does C have range-based for loops?

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.

What is a ranged based for loop?

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() .

Does range-based for loop use iterator?

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.

Is range-based for loop faster?

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).


2 Answers

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).

like image 176
Nicol Bolas Avatar answered Sep 18 '22 00:09

Nicol Bolas


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.

like image 42
Nawaz Avatar answered Sep 21 '22 00:09

Nawaz