Как реализовать цикл от середины до начала последовательности с помощью итераторов? - PullRequest
0 голосов
/ 06 марта 2019

Я хочу перебрать коллекцию от середины до начала, но я не уверен, как лучше ее реализовать. Еще одна вещь, которая усложняет это, заключается в том, что у меня есть функция, где я должен передать итератор. Код, объясняющий мою проблему:

Первый подход:

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

Второй подход:

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

Каждый не очень интуитивно понятен. Первый из них имеет бесконечный цикл с разрывом, а второй имеет это длинное определение rmiddle, и я должен передать итератор как i.base () - 1, что не очень легко прочитать. Мне понадобится что-то вроде do-while, но сначала проверяется условие, затем выполняется код, даже если условие ложно, а затем завершается цикл. Есть ли лучший способ или шаблон, как иметь дело с чем-то вроде этого?

Ответы [ 2 ]

1 голос
/ 06 марта 2019

Ваш первый подход имеет проблему, потому что вы не следуете обычному шаблону - используйте [first, last [для диапазона, вы пытаетесь использовать [first, last] (последний включен):

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);
    }
}
0 голосов
/ 06 марта 2019

Так как вы используете

template <typename RandomIt> ...

Я предполагаю, что у вас есть RandomAccesssIterator.

RandomAccessIterator поддерживает оператор больше чем. Вы можете использовать:

// 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...