11

Is there any way to iterate over only a part of an array in the C++11 range-based loop? Say I have an int someArray[10000000] but I only want to iterate over the first n elements. Thus, I can't simply use

for(auto elem: someArray) {//doStuff}

Any way to limit the scope of the loop while still using the range-based goodies?

1
  • 1
    What are (in your opinion) the range-based goodies? What's wrong with an ordinary for loop? Commented Oct 21, 2015 at 20:47

5 Answers 5

8

Simply adapt the range to be a different type where begin() and end() do the right thing.

struct Slice {
  int* arr;
  size_t n;
  int* begin() { return arr; }
  int* end() { return arr + n; }
};

for(auto elem : Slice{someArray, 100}) {/*doStuff*/}
Sign up to request clarification or add additional context in comments.

4 Comments

Why not size_t for the size?
Shrug. Use that if you want to. An array used with range-based for is almost certainly global or automatic, so is unlikely to be too big for an int index. A system that can create an array of 10e7 probably has at least 32-bit int. If not, use a bigger type.
Why write code which usually works instead of always works?
So use a bigger type.
5

There is no C++11 way to do this without writing your own wrapper for it. An alternative option could be to use Range-V3 which has view::slice (see it live):

#include <iostream>

#include <range/v3/view.hpp>

int main() {
  int arr[10] = {1,2,3,4,5,6,7,8,9,10} ;

  using namespace ranges;

  auto rng = arr |  view::slice(3, 6);

  for( auto &item : rng )
  {
      std::cout << item << ", " ;
  }
  std::cout << std::endl ;
}

If on the other hand C++14 was available then GSL array_view would be a viable option:

gsl::array_view<int> av(arr+3,3) ;

for( auto &item : av )
{
    std::cout << item << ", " ;
}
std::cout << std::endl ;

gsl-lite offers a minimal GSL implementation that works in C++11.

Comments

4

With C++20 std::span can be used.

for (auto elem : std::span(someArray).first(n))
  std::cout << elem;

Comments

2

No. Not in the current standard.

There are some things in the making for C++17 that would make this possible, e.g. std::range and std::array_view.

But until then, just use the good old iterator or index for, it will be the most readable:

for(auto i = 0u; i < n; ++i)
{
    // do the stuffs on someArray[i]
}

Comments

0

The range-based for loop iterates over the entire range. What you could do is store an additional index that you check in each look.

size_t index = 0;
for(auto elem: someArray) 
{
   //doStuff

   if(index++ > n) break;
}

However, I don't see what you'd gain with this over a regular for loop.

Ofc, you could also use std::for_each on the desired sub-range, but I'd still prefer a traditional for loop.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.