Ava
Ava

Reputation: 838

How to implement a loop from the middle to the beginning of the sequence using iterators?

I want to iterate over a collection from the middle to the beginning but I'm not sure about best way to implement it. Another thing that complicates it is that I have a function where I have to pass an iterator. Code explaining my problem:

First approach:

template <typename RandomIt>
void Example(RandomIt first, RandomIt last)
{
    auto size = std::distance(first, last);
    RandomIt middle = std::next(first, size / 2 - 1);
    for (auto i = middle; ; --i)
    {
        OtherFunction(i);
        if (i == first) break;
    }
}

Second approach:

template <typename RandomIt>
void Example(RandomIt first, RandomIt last)
{
    auto size = std::distance(first, last);
    RandomIt middle = std::next(first, size / 2 - 1);
    auto rmiddle = std::make_reverse_iterator(std::next(middle, 1));
    auto rlast = std::make_reverse_iterator(first);
    for (auto i = rmiddle; i != rlast; ++i)
        OtherFunction(i.base()- 1);
}

Each one is not really intuitive. First one has infinite loop with break and the second one has that long definition of rmiddle and I have to pass iterator as i.base()- 1, not really easy to read. I would need something like do-while but first checking the condition, then executing code even if condition is false and then ending a loop. Is there a better way or a pattern how to deal with something like this?

Upvotes: 0

Views: 119

Answers (2)

R Sahu
R Sahu

Reputation: 206577

Since you are using

template <typename RandomIt> ...

I am assuming you have a RandomAccesssIterator.

RandomAccessIterator supports the greater-than operator. You can use:

// Take care of all items except first in the loop.
for (auto i = middle; i > first; --i)
{
    OtherFunction(i);
}

// Take care of first
OtherFunction(first);

Upvotes: 0

Slava
Slava

Reputation: 44238

Your first approach has an issue because you do not follow usual pattern - use [first,last[ for the range, you are trying to use [first,last] (last is included):

template <typename RandomIt>
void Example(RandomIt first, RandomIt last)
{
    auto size = std::distance(first, last);
    RandomIt middle = std::next(first, size / 2);
    for (auto i = middle; i != first;)
    {
        OtherFunction(--i);
    }
}

Upvotes: 1

Related Questions