Есть ли способ перебрать только часть массива в цикле на основе диапазона С ++ 11? Скажем, у меня есть int someArray[10000000], но я хочу перебрать только первые элементы n. Таким образом, я не могу просто использовать

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

Есть ли способ ограничить объем цикла, по-прежнему используя полезности на основе диапазона?

5
Straightfw 21 Окт 2015 в 22:36

4 ответа

Лучший ответ

Просто адаптируйте диапазон к другому типу, где begin() и end() делают правильные вещи.

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

for(auto elem : Slice{someArray, 100}) {/*doStuff*/}
5
Jonathan Wakely 22 Окт 2015 в 20:22

Цикл for на основе диапазона выполняет итерацию по всему диапазону. Что вы можете сделать, так это сохранить дополнительный индекс, который вы проверяете при каждом просмотре.

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

   if(index++ > n) break;
}

Однако я не вижу, что вы получите от этого по сравнению с обычным циклом for.

Конечно, вы также можете использовать std::for_each в желаемом поддиапазоне, но я все же предпочел бы традиционный цикл for.

0
Marius Bancila 21 Окт 2015 в 20:14

Нет. Не в текущем стандарте.

В C ++ 17 есть некоторые вещи, которые сделали бы это возможным, например std::range и std::array_view.

Но до тех пор просто используйте старый добрый итератор или индекс for, он будет наиболее читаемым:

for(auto i = 0u; i < n; ++i)
{
    // do the stuffs on someArray[i]
}
2
emlai 21 Окт 2015 в 20:37

В C ++ 11 нет способа сделать это без написания для него собственной оболочки. Альтернативным вариантом может быть использование Range-V3, в котором есть view::slice ( посмотреть вживую ):

#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 ;
}

Если, с другой стороны, был доступен C ++ 14, тогда GSL array_view был бы жизнеспособным вариантом:

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

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

gsl-lite предлагает минимальную реализацию GSL, которая работает на C ++ 11.

3
Shafik Yaghmour 5 Ноя 2015 в 21:19