2015-10-21 2 views
1

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

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

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

+1

Каковы (на ваш взгляд) * лайки на основе диапазона *? Что случилось с обычным циклом 'for'? – Walter

ответ

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*/} 
+2

Почему не 'size_t' для размера? –

+0

Shrug. Используйте это, если хотите. Массив, используемый с диапазоном 'for', почти наверняка глобальный или автоматический, поэтому вряд ли будет слишком большим для индекса' int'. Система, которая может создать массив из 10e7, вероятно, имеет как минимум 32-битный 'int'. Если нет, используйте больший тип. –

+3

Зачем писать код, который обычно работает, а не всегда работает? –

0

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

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

    if(index++ > n) break; 
} 

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

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

1

№ Нет в действующем стандарте.

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

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

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

Там нет C++ 11 способов сделать это без написания собственной обертки для него , Альтернативным вариантом может быть использование Range-V3, который имеет 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 ; 
} 

Если с другой стороны, 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.

Смежные вопросы