1

I know of the simple way to iterate, for instance, over every character of a string as so:

std::string some_string("Hello World");
for(auto character : some_string)
    std::cout << character << std::endl;

But is there a way to use this construction to also tell it to take steps, or take specific lengths of the container in this way? Or would I have to use the classic int i = 0; i < some_string.length(); i+=2 construction for iterating over the string indices and storing parts of it with string.substr()? For instance if I wanted to store every 2 characters of a string as a substring.

Jack Avante
  • 1,405
  • 1
  • 15
  • 32
  • 2
    No, that's not possible. You need a for loop using iterators, or an indexed loop. – πάντα ῥεῖ Oct 13 '20 at 13:49
  • You could write your own iterators for that. – tkausl Oct 13 '20 at 13:49
  • Unfortunate. I was hopeful with how advanced C++ got, especially in C++20. – Jack Avante Oct 13 '20 at 13:49
  • @tkausl Well, that's possible, but probably not worth the efforts. – πάντα ῥεῖ Oct 13 '20 at 13:50
  • 2
    Simple readable code > some hacky trick that looks cool. – Mansoor Oct 13 '20 at 13:51
  • 1
    @JackAvante -- The boost library has [stride iterators](https://www.boost.org/doc/libs/1_74_0/boost/compute/iterator/strided_iterator.hpp). Maybe in C++ 23 or beyond, they can be adopted by the standards committee. – PaulMcKenzie Oct 13 '20 at 13:56
  • `bool tiktok = false; for (auto c : s) { tiktok = !tiktok; if (tiktok) continue; cout << c << "\n"; }` – Eljay Oct 13 '20 at 13:56
  • 1
    `views::stride(n)` from [ranges-v3](https://ericniebler.github.io/range-v3/index.html) can do this (`for (auto character : some_string | views::stride(2))`). Also [`boost::adaptors::strided(n)`](https://www.boost.org/doc/libs/1_74_0/libs/range/doc/html/range/reference/adaptors/reference/strided.html) with similar syntax – Artyer Oct 13 '20 at 14:08
  • 1
    @Artyer You should post `views::stride()` as an answer to both, I would say, since `range-v3` is the basis of Standard Ranges and therefore there's a good change the stdlib will get `stride()` in future. – underscore_d Oct 13 '20 at 14:15

1 Answers1

3

This range based for loop (from cppreference):

for ( init-statement(optional)range_declaration : range_expression ) loop_statement 

is equivalent to:

{

    init-statement
    auto && __range = range_expression ;
    auto __begin = begin_expr ;
    auto __end = end_expr ;
    for ( ; __begin != __end; ++__begin) {

        range_declaration = *__begin;
        loop_statement

    }

} 

(see link for what begin_expr and end_expr are and more details)

There is no (easy) way to make it increment more than one. The advantage of the range based for loop is that you need not care about indices or iterators. If you want to do something with indices, then using the range based loop is not an advantage.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185