Цитирование на итераторах С++, начиная со второго (или n-го) элемента

Я ищу читаемый, элегантный способ сделать следующее на С++, здесь показано на Python:

for datum in data[1:]:
    do work.

Итераторы данных, о которых идет речь, могут не поддерживать итераторы с произвольным доступом, поэтому я не могу просто использовать:

for (mIter = data.begin() + 1; mIter != data.end(); mIter++)

Лучшее, что я придумал, следующее:

iterable::iterator mIter = data.begin();
for (mIter++;  mIter != allMjds.end(); mjdIter++) {
    do work.
}

Он не слишком длинный, но он вряд ли раскрыт - на первый взгляд это на самом деле выглядит как ошибка!

Другое решение - иметь вспомогательную функцию "n-го элемента", я думаю. Любые более прохладные идеи?

Ответ 1

Вы можете использовать std::next(iter, n) для достижения линейного времени. Вы также можете использовать стандартный алгоритм std::advance, хотя он не так прост в использовании (он принимает итератор неконстантной ссылкой и не возвращает его).

Например,

for (mIter = std::next(data.begin()); mIter != data.end(); ++mIter)

или,

mIter = data.begin();
std::advance(mIter, 1);
for (; mIter != data.end(); ++mIter)

Обратите внимание, что вы должны убедиться, что data.size() >= 1, иначе код будет катастрофическим.

Ответ 2

#include <iterator>

iterator iter = data.begin();
for (advance(iter, 1); iter != data.end(); ++iter)
{
  // do work
}

Это полагается нa >= 1 элемент в data, чтобы избежать исключения.

Ответ 3

Вы можете попробовать:

for (mIter = data.begin() ; ++mIter != data.end() ; )

но вам нужно убедиться, что если data.begin () == data.end () выполнение ++mIter не вызывает проблемы.

Поскольку это нестандартный цикл цикла, использование цикла while может быть более уместным, так как существует меньше предвзятых представлений о том, как они работают, то есть люди, смотрящие на ваш код, с большей вероятностью читают инструкцию while, чем оператор for так как обычно существует модель того, как цикл for должен работать в их голове.

mIter = data.begin ();

while (++mIter != data.end ())
{
}

Ответ 4

Вы можете использовать boost:: next для этого (но вы должны быть уверены, что на самом деле в списке есть элемент в нем):

#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>

#include <boost/assign.hpp>
#include <boost/next_prior.hpp>
using namespace boost::assign;

int main()
{
    std::list<int> lst = list_of(23)(9)(84)(24)(12)(18);
    std::copy(boost::next(lst.begin()), lst.end(), std::ostream_iterator<int>(std::cout, " "));
    return 0;
}

Ответ 5

iterable::iterator mIter = data.begin();    
std::for_each(++mIter, data.end(), some_func);

где some_func содержит код, который вы хотите выполнить... вы можете даже тривиализировать его с помощью простой функции-обертки

template <typename _cont, typename _func>
for_1_to_end(_cont const& container, some_func func)
{
  typename _cont::const_iterator it = _cont.begin();
  std::for_each(++it, _cont.end(), func);
}