Моя проблема более сложна, чем эта, поэтому я сузил ее до очень простого примера, который показал бы мне достаточно, чтобы уметь справляться с остальными.
Скажем, у меня есть входной итератор. Я хочу создать новый итератор ввода, полученный из него, где каждый элемент представляет собой комбинацию нескольких последовательных элементов исходного ввода со следующим шаблоном. Длина серии кодируется во входной последовательности.
Входной сигнал:
{ 1 1 2 3 4 4 6 7 8 9 ... }
Выход:
{ (1) (3+4) (6+7+8+9) ... }
Я думал, что такая функция может обрабатывать отдельный элемент и увеличивать входной итератор начала (передаваемый по ссылке). В моих комментариях есть несколько вопросов, и я хотел бы знать, есть ли хороший способ сделать это для всего потока элементов.
РЕДАКТИРОВАТЬ: Я знаю, что есть ошибка в вызове std::advance
, когда итератор tmp
увеличивается до точно end
, что будет допустимо для этого кода. Давайте сосредоточимся на остальных моих вопросах, и я исправлю это. Редактировать 2: теперь нужно исправить?
template<class TInputIterator, class TOutputIterator>
void process_single(TInputIterator& begin, TInputIterator end, TOutputIterator destination)
{
std::iterator_traits<TInputIterator>::value_type run_length = *begin;
++begin;
// is there a better way to specify run_length elements to accumulate() without having to call advance() here?
TInputIterator tmp(begin);
std::advance(tmp, run_length);
// Edited: this condition should work for the different kinds of iterators?
if ((end < tmp) || (std::distance(begin, tmp) != run_length))
throw std::range_error("The input sequence had too few elements.");
// std::plus is the default accumulate function
*destination = std::accumulate(begin, tmp, 0/*, std::plus<TInputIterator::value_type>()*/);
// should I use std::swap(begin, tmp) here instead?
begin = tmp;
}
Редактировать 3: В ответ на ответы это будет лучше?
template<class TInputIterator, class TOutputIterator>
TInputIterator process_single(TInputIterator begin, TInputIterator end, TOutputIterator destination)
{
typedef std::iterator_traits<TInputIterator>::value_type value_type;
value_type run_length = *begin;
++begin;
value_type sum = 0;
while (run_length > 0 && begin != end)
{
sum += *begin;
++begin;
--run_length;
}
if (run_length)
{
throw std::range_error("The input sequence had too few elements.");
}
*destination = sum;
return begin;
}
template<class TInputIterator, class TOutputIterator>
void process(TInputIterator begin, TInputIterator end, TOutputIterator destination)
{
while (begin != end)
{
begin = process_single(begin, end, destination);
}
}