Question

If I got that right I can use this to iterate over a fixed range:

for(int i: {1, 2, 3, 4, 5})
    do_sth(i);

And this is the same thing:

vector<int> v{1, 2, 3, 4, 5};
for(int i: v)
    do_sth(i);

But what if I want to iterate over the range of 1, ..., 100 and already know that at compile time? What is the most beautiful way to do that? What the most efficient? What the shortest?

Edit: of course I could write a regular for loop, but the actual use case would involve more complicated content than ints.

I just oversimplified the example a bit.

Was it helpful?

Solution 2

You can "easily" write a for-range-compatible class that represents an integer range. You just have to write the iterators for it.

Or you can use Boost.Range's counting_range, which is exactly that.

OTHER TIPS

for( int i = 1; i <= 100; ++i )
{
    do_sth( i );
}

?

If you really want it in a container, you can fill a container using the std::iota function. Otherwise use a normal for loop.

Use a range-for with a function template:

namespace detail
{
    template <int... Is>
    struct index { };

    template <int N, int... Is>
    struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };

    template <int... Is>
    struct gen_seq<0, Is...> : index<Is...> { };
}

template <int... Is>
std::array<int, sizeof...(Is)> range(detail::index<Is...>)
{
    return {{ Is... }};
}

template <int N>
std::array<int, N> range()
{
    return range(detail::gen_seq<N>{});
}

Example:

for (auto i : range<5>())
{
    do_sth(i);
}

Example of an iterator-based technique, as Sebastian Redl mentioned:

class range {
public:
    struct rangeIt{
        rangeIt(int v) : _v(v){}
        int operator*()const{return _v;}
        void operator++(){_v++;}
        bool operator!=(const rangeIt & other)const{ return _v != other._v;}
    private:
        int _v;
    };
    range(int a, int b):_a(a),_b(b){}
    rangeIt begin() const { return rangeIt(_a); }
    rangeIt end() const { return rangeIt(_b); }
private:
    int _a, _b;
};

Then it can be used like this:

for(int i : range(0, 100)) {
  printf("%d\n", i);
}
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> operator"" _r(const char* text, const size_t)
{
    string txt(text);

    auto delim  = txt.find('-');
    auto first  = txt.substr( 0, delim);
    auto second = txt.substr(delim + 1);

    int lower = stoi(first);
    int upper = stoi(second);

    vector<int> rval(upper - lower);

    generate(rval.begin(), rval.end(), [&]{ return lower++; } );

    return rval;
}

int main() 
{
    for(auto& el : "10-100"_r)
        cout<<el<<"\n";
}

Big runtime overhead, error prone ( mainly my implementation )... just the way I like it !

But it does solve the problem and even has a not-that-ugly syntax :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top