# A simple counting loop class

EDIT: Updated version available here: A counting loop class v2

Ranges (C++20) aren't quite ready, so until then, I needed a reliable counting loop class that ​works fairly well to replace the old-style for loops:

for (int i = x; i <= y; ++i)


With a simple foreach loop:

for (int i: loop (x, y))


As implemented, it is inclusive for start value and end value.

Algorithms are supported by having all the typedefs needed for a contiguous_iterator.

Here is the class:

#include <iterator>

template <class T>
class loop
{
public:
class iterator
{
public:
using value_type=std::remove_cv_t<T>;
using difference_type=value_type;
using pointer=T*;
using reference=T&;
using iterator_category=std::random_access_iterator_tag;
using iterator_concept=std::contiguous_iterator_tag;
using self_type=iterator;
iterator(T x) : curr{x} {}
T operator*()
{
return curr;
}
iterator& operator++()
{
curr++;
return *this;
}
bool operator==(const iterator& rhs) const
{
return curr == rhs.curr;
}
difference_type operator-(const iterator& rhs)
{
return curr-rhs.curr;
}
private:
T curr;
};
loop(T x, T y) : front{x}, back{y} {}
iterator begin()
{
return front;
}
iterator end()
{
return back + 1;
}
private:
T front;
T back;
};


And some usage examples:

int foo(int x, int y)
{
int sum=0;
for (auto z : loop(x, y))
{
sum+=z;
}
return sum;
}

#include <algorithm>

int goo(int x, int y, int z)
{
loop range(x,y);
auto f=std::find(range.begin(), range.end(), z);
if (f != range.end())
{
return *f;
}
return x-1;
}

int ggg()
{
return goo(3, 37, 17);
}

• What's "not ready" about the Ranges library? It seems pretty workable to me. Nov 9 at 9:08

We currently accept non-numeric types such as other iterators - is that intended?

I'm not convinced this is a good choice when T is unsigned:

    using difference_type=value_type;


We probably want to use std::make_signed_t<value_type>. Or perhaps even std::make_signed_t<std::common_type_t<int,value_type>> so we don't have truncating conversion with smaller types (which get promoted to int).

Unless I'm mistaken, an iterator is required to support both preincrement and postincrement, so we need operator++(int) as well (this one returns a new iterator, of course).

Since the iterator type is actually also the const iterator, we can declare begin() and end() as const.

Consider also providing front() and back() - you'll want to re-name the private members (perhaps first and last?).

Possible enhancement: consider also supporting a step increment between values (default 1).

• Thanks, been working on your suggestions and adding step -- also you can see the issue with ranges in clang there ("ranges aren't ready") its wrapped with an #if 0 -- godbolt.org/z/Px3nfYqPx Nov 10 at 4:53