Is there a compact equivalent to Python range() in C++/STL

Solution 1:

In C++11, there's std::iota:

#include <vector>
#include <numeric> //std::iota

std::vector<int> x(10);
std::iota(std::begin(x), std::end(x), 0); //0 is the starting number

Solution 2:

There is boost::irange:

std::vector<int> x;
boost::push_back(x, boost::irange(0, 10));

Solution 3:

I ended up writing some utility functions to do this. You can use them as follows:

auto x = range(10); // [0, ..., 9]
auto y = range(2, 20); // [2, ..., 19]
auto z = range(10, 2, -2); // [10, 8, 6, 4]

The code:

#include <vector>
#include <stdexcept>

template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop, IntType step)
{
  if (step == IntType(0))
  {
    throw std::invalid_argument("step for range must be non-zero");
  }

  std::vector<IntType> result;
  IntType i = start;
  while ((step > 0) ? (i < stop) : (i > stop))
  {
    result.push_back(i);
    i += step;
  }

  return result;
}

template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop)
{
  return range(start, stop, IntType(1));
}

template <typename IntType>
std::vector<IntType> range(IntType stop)
{
  return range(IntType(0), stop, IntType(1));
}

Solution 4:

I've been using this library for this exact purpose for years:

https://github.com/klmr/cpp11-range

Works very well and the proxies are optimized out.

for (auto i : range(1, 5))
    cout << i << "\n";

for (auto u : range(0u))
    if (u == 3u) 
        break;
    else         
        cout << u << "\n";

for (auto c : range('a', 'd'))
    cout << c << "\n";

for (auto i : range(100).step(-3))
    if (i < 90) 
        break;
    else        
        cout << i << "\n";

for (auto i : indices({"foo", "bar"}))
    cout << i << '\n';