Что за аккуратный способ перебрать целый ряд целых чисел в C++20?
Когда мы хотим перебрать диапазон чисел, от 0
в n
многие (большинство?) из нас пишут:
for (int i=0; i < n; ++i)
Но - мне не нравится этот код. Я бы лучше написал что-то вроде
for (auto i : magic_goes_here(0,n)) { /* ... */ }
с таким же телом петли. Позволяет ли язык C++20 (и, возможно, стандартная библиотека) что-то разумное заменить частью "magic_goes_here"?
Фон
Семь лет назад этот вопрос был задан на Stackru: лучший способ перебрать целый ряд целых чисел в C++11?
С тех пор у нас вышли две языковые версии - C++14 и C++17; и C++20 не за горами (проект комитета был доработан в июле 2019 года). Все могло измениться.
PS - Еще один связанный с этим вопрос: существует ли класс диапазона в C++ 11 для использования с диапазоном, основанным на циклах?
1 ответ
Этот ответ основан на сообщениях в списках рассылки std-предложения C++ в этой теме.
Благодаря поддержке диапазонов в C++20 вы сможете написать:
for (auto i : std::views::iota(0, n)) { /* ... */ }
вместо оригинального цикла. Вот и все.
Если вы хотите что-то более короткое, вы можете определить:
template <std::integral T> auto index_range(T a, T b) { return std::views::iota(a, b); }
и теперь ваш цикл for становится:
for (auto i : index_range(0, n)) { /* ... */ }
но это немного обмануть, так как его нет в стандартной библиотеке.
Примечания:
std::ranges::iota
какstd::iota()
за исключением того, что он не заполняет контейнер 0...n
-1, он лениво возвращает эти значения как основанные на диапазоне для итераторов цикла через него.- Код здесь использует
std::integral
концепция, поэтому класс шаблона не может быть любого типа; концепции - это новая особенность C++20.) -
ranges-v3
библиотека, на которой основаны диапазоны C++20, уже доступна для C++14 и имеетranges::v3::iota_view
Таким образом, вы могли бы в основном делать все вышеперечисленное с C++14. - Если это предложение будет принято,
upto()
будет стандартизирован в C++23, наряду с несколькими другими связанными вспомогательными функциями.